我有这个访客模式实现:
class Visitor {
public:
Visitor() {}
void visit(A *a){ a->doSomething(); }
void visit(B *b){ b->doSomething(); }
};
class Base {
public:
Base() {}
virtual void accept(Visitor *v) = 0;
};
class A: public Base {
public:
A():Base() {}
void accept(Visitor *v) override { v->visit(this) };
.....
};
class B: public Base {
public:
B():Base() {}
void accept(Visitor *v) override { v->visit(this) };
};
问题是,A
和B
在访问者实施中的类型不完整。但我不想将实现放在单独的源文件中。
有没有办法将它放在一个头文件中?
答案 0 :(得分:1)
转发声明A
和B
。将您的visit(A*a);
和visit(B*b);
移到Visitor的类声明之外,并在A
和B
类之后声明它。为避免重复的符号,将其放入头文件,例如Header.h:
//forward declarations
class A;
class B;
class Visitor {
public:
Visitor() {}
void visit(A *a);
void visit(B *b);
};
class Base {
public:
Base() {}
virtual void accept(Visitor *v) = 0;
};
class A: public Base {
public:
A():Base() {}
void accept(Visitor *v) override { v->visit(this); };
void doSomething(){};
};
class B: public Base {
public:
B():Base() {}
void accept(Visitor *v) override { v->visit(this); };
void doSomething(){};
};
此声明应放在cpp文件中,以避免重复的符号,例如将其添加到main.cpp:
#include "Header.h"
//outside declarations of methods
void Visitor::visit(A *a){ a->doSomething(); }
void Visitor::visit(B *b){ b->doSomething(); }
答案 1 :(得分:0)
重点是:
只要你有两个类(例如A和Visitor),并且每个人的实现都需要另一个声明,你就不能合并实现和声明。
在你的情况下:
class Visitor {
public:
// Visitor's implementation needs A's declaration
void visit(A *a){ a->doSomething(); }
};
class A {
public:
// A's implementation needs Visitor's declaration
void accept(Visitor *v) { v->visit(this) };
void doSomething() { ... };
};
希望在分离文件中声明和实现的原因之一。 还有很多其他原因,包括差异编译时间。
请问为什么要在同一个文件中实现所有这些?
但是:
根据您要实现的目标,您可能想要欺骗它。但这将是一个痛苦的维持。 除非有非常好的和不寻常的理由,否则我永远不会这样做。
例如,我认为这样的事情应该有效:
class Doer {
public:
// Doer's implementation don't needs Visitor's declaration
virtual void doSomething()=0;
};
class A;
class Visitor {
public:
// Visitor's implementation needs Doer's declaration
void visit(A *a){ ((Doer*)a)->doSomething(); }
};
class A: public Doer {
public:
// A's implementation needs Visitor's declaration
void accept(Visitor *v) { v->visit(this) };
void doSomething() override { ... };
};
再次,如果您有选择:不要那样做。喜欢拆分文件。这种解决方法,即使有详细记录,也很难维护。