代码组织

时间:2018-05-02 10:23:41

标签: c++ code-organization visitor

我有这个访客模式实现:

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在访问者实施中的类型不完整。但我不想将实现放在单独的源文件中。

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

2 个答案:

答案 0 :(得分:1)

转发声明AB。将您的visit(A*a);visit(B*b);移到Visitor的类声明之外,并在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(); }

答案 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 { ... };
};

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