C++中的泛型策略模式

Som*_*mer 1 c++ templates design-patterns interface strategy-pattern

我正在尝试用C++实现策略模式,而我在查找正确的语法时遇到了麻烦.这是我想要做的一个(相当简单的)java代码示例:

public static interface Processor<T> {

    public void process(T toProcess);
}

public static class Printer implements Processor<String> {

    @Override
    public void process(String toProcess) {
        System.out.println(toProcess);
    }

}

public static class StringHandler {

    public void handleData(Processor<String> processor) {
        processor.process("Hello World!");
    }
}

public static void main(String... args) throws Exception {
    new StringHandler().handleData(new Printer());
}
Run Code Online (Sandbox Code Playgroud)

尝试使用C++等价物:

#include <string>

using namespace std;

template <typename T>class Processor {
public:
    virtual void process(T rhs) = 0;
};

class Printer : public Processor<string*> {
public:

    void process(string* a) {
        printf("string = %s\n", a->c_str());
    }
};

class StringHandler {
public:

    void handleData(Processor<string*> processor) {
        string hello = "Hello World!!";
        processor.process(&hello);
    }
};

int main(int argc, char** argv) {
    StringHandler h;
    Printer p;
    h.handleData(p);
}
Run Code Online (Sandbox Code Playgroud)

当我尝试编译代码时,我收到以下错误:

Undefined symbols for architecture x86_64:
  "Processor<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*>::process(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*)", referenced from:
      StringHandler::handleData(Processor<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >*>) in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Run Code Online (Sandbox Code Playgroud)

有关我的C++代码无法编译的原因,或者如何在C++中实现此模板模式的任何见解,将不胜感激.使用C++ 98编译的解决方案更可取,但我也对使用Functional库的方法感兴趣.

Jer*_*fin 6

你试图传递一个Processorby值而不是引用,这需要实例化Processor(这是不可能的,因为它是一个抽象类).

您可以通过引用传递它来修复它:

void handleData(Processor<string*> &processor) {
    // ...
Run Code Online (Sandbox Code Playgroud)

也就是说,你的方法在我看来很像你仍然基本上编写Java(因为糟糕的措施引入了一点C),只是改变语法足以让C++编译器接受它.

在C++中,策略模式通常将实现为模板参数.我可能会更像这样编写代码:

struct print {
    void operator()(std::string const &s) const {
        std::cout << "string = " << s << "\n";
    }
};

template <class Process>
void handle(Process p) {
    p("Hello World!!");
};

int main() {
    handle(print());
}
Run Code Online (Sandbox Code Playgroud)

但请注意,在许多情况下,策略部分仅在一个地方使用,在这种情况下,将其定义为lambda表达式是有意义的:

handle([](std::string const &s) { std::cout << "string = " << s << "\n"; });
Run Code Online (Sandbox Code Playgroud)


Bar*_*rry 5

问题是你如何声明handleData:

void handleData(Processor<string*> processor) {
Run Code Online (Sandbox Code Playgroud)

Processor<T>是一个抽象类.它无法构建.如果可以,您将切片对象的派生部分,这是process(T )生命的实际实现.gcc为我提供了一个更明确的错误:

错误:无法将参数声明processor为抽象类型Processor<std::basic_string<char>*>

你需要改为processor参考:

void handleData(Processor<string*>& processor) {
Run Code Online (Sandbox Code Playgroud)