代码组织

Code organizing

本文关键字:代码      更新时间:2023-10-16

>我有这个访问者模式实现:

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) };
};

问题是AB在 Visitor 实现中具有不完整的类型。但我不想将实现放在单独的源文件中。

有没有办法把它放在一个头文件中?

做前向声明AB。将您的visit(A*a);visit(B*b);移到访问者的类声明之外,并在AB类之后声明它。为了避免重复的符号,请将其放入头文件,例如 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(); }

重点是:

只要您有两个类(例如 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 { ... };
};

再一次,如果你有选择:不要那样做。更喜欢拆分文件。这种解决方法,即使有很好的文档记录,也很难维护。