循环依赖类中的Typedef

时间:2016-04-08 19:49:27

标签: c++ class templates typedef circular-dependency

我有几个类(FBSDKGraphRequestHandler completionHandler = ^ (FBSDKGraphRequestConnection * connection, id result, NSError * error) {AB),每个类都有一个带有模板化(C)类型的成员,具体取决于另一个类的不完整类型(圆)。我想键入dede类型(Ptr<...>),如下所示。这似乎不起作用 - 我的编译器告诉我以下内容:

::ptr

但是,使用In file included from B.hpp:6:0, from A.hpp:6: C.hpp:13:8: error: ‘ptr’ in ‘class A’ does not name a type A::ptr a; ^ 代替T*会使其正常运行。我该如何解决这个问题?

A.hpp:

T::ptr

B.hpp:

#ifndef TEST_INCLUDE_A
#define TEST_INCLUDE_A 1

class A;

#include "B.hpp"

#include "P.hpp"

class A {
public:
    typedef Ptr<A> ptr;
    B::ptr b;
};

#endif

C.hpp:

#ifndef TEST_INCLUDE_B
#define TEST_INCLUDE_B 1

class B;

#include "C.hpp"

#include "P.hpp"

class B {
public:
    typedef Ptr<B> ptr;
    C::ptr c;
};

#endif

P.hpp:

#ifndef TEST_INCLUDE_C
#define TEST_INCLUDE_C 1

class C;

#include "A.hpp"

#include "P.hpp"

class C {
public:
    typedef Ptr<C> ptr;
    A::ptr a;
};

#endif

3 个答案:

答案 0 :(得分:2)

为了解决循环依赖,你只需要给编译器一个手,并传授一些关于ptr将在另一个类中的预知,即:你知道A::ptrPtr<A>,等等。

online demo

class A;
class B;

template<typename T>
struct Ptr { T* ptr_t; };

class A {
public:
    using ptr = Ptr<A>;
    Ptr<B> b;
};

class B {
public:
    using ptr = Ptr<B>;
    Ptr<A> a;
};

int main() {
    A a;
    B b;
    a.b.ptr_t = &b;
    b.a.ptr_t = &a;

    A::ptr aptr;
    B::ptr bptr;
    aptr.ptr_t = &a;
    bptr.ptr_t = &b;
    a.b = bptr;
    b.a = aptr;
}

答案 1 :(得分:1)

某些操作只能在完整类型上执行。其中之一是来自[basic.def.odr]:

  

如果符合以下条件,则类型T必须完整:
   - [...]
   - 类成员访问运算符应用于类型T(5.2.5)或
的表达式    - [...]

撰写A::ptr需要A完成。在我们定义A时,C尚未完成,因此这是一个错误。

另一方面,当您编写A*时,需要A才能完成。将指向不完整类型的指针(或引用)作为成员就可以了。

答案 2 :(得分:1)

我的建议:

  1. 稍微更新P的定义以定义派生的类型名称。

    template<class T>
    class Ptr {
    public:
        using ptr_t = T*;
        ptr_t ptr;
    };
    
  2. 更新A.hpp,B.hpp和C.hpp,分别仅依靠BCA的前向声明。

    A.hpp。

    的更新版本
    #ifndef TEST_INCLUDE_A
    #define TEST_INCLUDE_A 1
    
    #include "P.hpp"
    
    class B;
    
    class A {
       public:
          typedef Ptr<A> ptr;   // This does not seem useful any longer
                                // It can probably be removed.
          Ptr<B> b_ptr;
    };
    
    #endif
    

    同样更新B.hpp和C.hpp。