如何用没有头的共享基类解决循环类依赖?

时间:2015-05-05 16:58:52

标签: c++ c++11 visual-studio-2012 circular-dependency

所以我创建的项目涉及将矢量嵌套在彼此内部,但结构不会编译。我认为这是循环依赖的情况,但我所看到的所有修复似乎只适用于涉及头文件和单独翻译单元的代码。

#include <iostream>
#include <vector>

class A {
public:
    virtual ~A();
};

// The following forward declaration statements didn't solve the
// compiler error:
// class C;
// class C : public A;

class B : public A {
    std::vector<A*> Avector;    
public:
    void addC(C* Cin){Avector.push_back(Cin);}
    ~B();
};

class C : public A {
    std::vector<A*> Avector;        
public:
    void addB(B* Bin){Avector.push_back(Bin);}
    ~C();
};

int main() {
    B b;
    C c;
    b.addC(&c);
    c.addB(&b);
}

我已尝试用

声明
class C;
Class C : public A;

但似乎都没有效果。

我得到的错误是:

\test\test\source.cpp(15): error C2061: syntax error : identifier 'C'
\test\test\source.cpp(15): error C2065: 'Cin' : undeclared identifier

这种代码是否可实现?

2 个答案:

答案 0 :(得分:7)

  

“...但我见过的所有修补程序似乎只适用于涉及头文件和单独翻译单元的代码。”

我完全同意像 Resolve circular dependencies in c++ 这样的流行问答并没有真正回答你如何在单个实现文件(标题或不标题)中处理此问题的问题。

然而,恕我直言,它被认为是更好的做法(并且你可以通过these pointers选择),将标题和实现/定义中的类声明分离到他们自己的翻译单元。
即使只使用标头(例如模板类)库,您应该考虑提供单独的类声明(没有内联代码),并在单独的源文件中提供实现,包含在那里。

你的问题实际上就在这里:

class B : public A {
    // ...
    void addC(C* Cin) { Avector.push_back(Cin); }
                   // ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    // ...
};

此时(即使使用class C;的前向声明),编译器也不知道如何将C*转换为A*,因为缺少有关继承关系的信息(不,你不能像class C : public A;)那样进行前瞻声明。

  

“这种代码是否可实现?”

您可以在一个翻译单元/标题文件中执行所有操作:

不是使用B的类声明来内联函数定义,而是应该在完全声明class C之后将其分开:

class C;

class B : public A {
    // ...
    void addC(C* Cin);
};

class C : public A {
    // ...
};

inline void B::addC(C* Cin) { Avector.push_back(Cin); }

class C无论如何都会看到class B的完整声明(因为声明顺序)。因此可以使用实现

void addB(B* Bin) { Avector.push_back(Bin); }

来自class C声明。

答案 1 :(得分:1)

我试过向前声明,我尝试在第二部分之后放置函数实现,但我没有同时尝试过。 10年后用户在Google上搜索的固定代码:

  #include<iostream>
    #include<vector>

    using namespace std;

    class C;

    class A
    {
    public:
        virtual ~A();
    };

    class B : public A
    {
    public:
        vector<A*> Avector;

        void addC(C* Cin);
        ~B();
    };

    class C : public A
    {
    public:
        vector<A*> Avector;

        void addB(B* Bin)
        {
            Avector.push_back(Bin);

        };
            ~C();
        };

    void B::addC(C* Cin)
    {
        Avector.push_back(Cin);
    }

    int main()
    {

    }

我要感谢πάνταῥεῖ,并向Jarod42致敬。