Man*_*d3r 1 c++ visitor-pattern
我想像这样在 C++ 中实现访问者模式:
class Visitor{
public:
virtual ~Visitor();
virtual void visit(C & t)=0;
};
class V : public Visitor{
public:
void visit(C &c);
};
class C{
public:
void accept(Visitor &v){ v.visit(*this); }
};
Run Code Online (Sandbox Code Playgroud)
但是编译器抱怨大约 2 个语法错误:未知标识符 C 和访问者。问题出在哪儿?
目前编译器看到
virtual void visit(C & t)=0;
Run Code Online (Sandbox Code Playgroud)
名字C未知。
你需要前瞻性声明class C前Visitor
class C;
class Visitor{
...
}
Run Code Online (Sandbox Code Playgroud)
在 C++ 语言中,编译器不会预先查找尚未定义的名称,或者更好地说,有时会查找,有时不会。
你可以说例如
struct Foo
{
Foo(int x) : m_x(x) { }
int m_x;
};
Run Code Online (Sandbox Code Playgroud)
m_x即使您在定义内容之前使用,编译器也不会抱怨m_x,但是在模块级别,这种前瞻性不存在:
struct Foo
{
Bar *p; // Error, Compiler doesn't know what Bar is
};
// Too late, the compiler is not going to read down here while
// analyzing Foo.
struct Bar
{
int x;
};
Run Code Online (Sandbox Code Playgroud)
如何解决在定义某些东西之前需要使用它的情况?通过使用特殊的“前向声明”,您只需声明将存在具有该名称的内容,然后您稍后在特定中定义它是什么......例如
struct Foo; // There will be a struct Foo defined somewhere
struct Bar
{
Foo *p; // Fine, even if the compiler doesn't really know Foo
};
struct Foo
{
Bar *q; // Fine and no forward needed... Bar is known at this point
};
Run Code Online (Sandbox Code Playgroud)
或多或少的规则是:在单个类中,所有方法都可以看到所有其他方法和所有成员,即使它们是稍后在类中定义的,在模块级别,每个名称都必须在使用之前已知。
有时需要更复杂的模式,例如
struct Foo;
struct Bar
{
void doit(Bar x);
};
struct Foo
{
void doit_too(Foo x);
};
void Foo::doit(Bar x) { ... }
void Bar::doit_too(Foo x) { ... }
Run Code Online (Sandbox Code Playgroud)
在最后一种情况下,您被迫将两个方法的实现放在两个类的声明之后,因为仅仅知道这Foo是一个类不足以编译复制操作(注意方法中的参数已按值传递,而不是通过指针或引用)。