C++ 中的策略模式与泛型
Strategy Pattern In C++ With Generics
我正在尝试用 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());
}
尝试 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);
}
当我尝试编译代码时,出现以下错误:
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)
任何有关为什么我的 C++ 代码无法编译或如何在 C++ 中实现此模板模式的见解,将不胜感激。使用 C++98 编译的解决方案将是更可取的,尽管我也对使用函数库的方法感兴趣。
问题在于您如何声明 handleData
:
void handleData(Processor<string*> processor) {
Processor<T>
是一个摘要 class。它无法构建。如果可以,您将 slice 对象的派生部分,这是 process(T )
的实际实现所在的位置。 gcc 为我提供了更清晰的错误:
error: cannot declare parameter processor
to be of abstract type Processor<std::basic_string<char>*>
您需要参考您的 processor
:
void handleData(Processor<string*>& processor) {
您正在尝试通过值而不是引用传递 Processor
,这需要实例化 Processor
(这是不可能的,因为它是抽象的 class)。
您可以通过引用来解决这个问题:
void handleData(Processor<string*> &processor) {
// ...
就是说,在我看来,您的方法很像您基本上仍在编写 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());
}
但是请注意,在很多情况下,策略部分只用在一个地方,在这种情况下,将其定义为 lambda 表达式是有意义的:
handle([](std::string const &s) { std::cout << "string = " << s << "\n"; });
我正在尝试用 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());
}
尝试 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);
}
当我尝试编译代码时,出现以下错误:
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)
任何有关为什么我的 C++ 代码无法编译或如何在 C++ 中实现此模板模式的见解,将不胜感激。使用 C++98 编译的解决方案将是更可取的,尽管我也对使用函数库的方法感兴趣。
问题在于您如何声明 handleData
:
void handleData(Processor<string*> processor) {
Processor<T>
是一个摘要 class。它无法构建。如果可以,您将 slice 对象的派生部分,这是 process(T )
的实际实现所在的位置。 gcc 为我提供了更清晰的错误:
error: cannot declare parameter
processor
to be of abstract typeProcessor<std::basic_string<char>*>
您需要参考您的 processor
:
void handleData(Processor<string*>& processor) {
您正在尝试通过值而不是引用传递 Processor
,这需要实例化 Processor
(这是不可能的,因为它是抽象的 class)。
您可以通过引用来解决这个问题:
void handleData(Processor<string*> &processor) {
// ...
就是说,在我看来,您的方法很像您基本上仍在编写 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());
}
但是请注意,在很多情况下,策略部分只用在一个地方,在这种情况下,将其定义为 lambda 表达式是有意义的:
handle([](std::string const &s) { std::cout << "string = " << s << "\n"; });