Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 代码组织_C++_Code Organization_Visitor - Fatal编程技术网

C++ 代码组织

C++ 代码组织,c++,code-organization,visitor,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 Ba

我有一个访问者模式实现:

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


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

要点是:

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

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

执行前向声明
A
B
。移动
访问(A*A)
访问(B*B)在访客类别声明之外,并在
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(); }

“这是将其放在单个头文件中的一种方式吗?”为什么要将实现放在头文件中?如果将实现放在源文件中,则“类型不完整”不会有问题。请尝试转发声明。@AlexeyUsachov,但仍不允许在头文件中包含此类方法的实现。
a
b
类型不完整的问题提示问题在于方法调用,而不是
a
b
的用法。就我所见,最终需要将某个东西的实现移动到源文件,而没有纯头实现的解决方案。如果在多个源文件中包含这样一个文件,会发生什么?一旦你尝试将链接器链接到最终应用程序,难道你没有收到链接器错误吗?@AlgirdasPreidžius是的,谢谢你的评论,我已经对我的答案进行了改进,以避免链接器可能出现重复错误