【问题标题】:Typedefs in circular-dependend classes循环依赖类中的 Typedef
【发布时间】:2016-04-08 19:49:26
【问题描述】:

我有几个类(ABC),每个类都有一个模板(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* 而不是 T::ptr 可以使其正常工作。我该如何解决?

A.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

B.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

C.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

P.hpp:

#ifndef TEST_INCLUDE_PTR
#define TEST_INCLUDE_PTR 1

template<class T>
class Ptr {
public:
    T* ptr_t;
};

#endif

【问题讨论】:

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


    【解决方案1】:

    为了解决循环依赖关系,您只需要帮助编译器并预知ptr 在另一个类中的含义,即:您知道@ 987654323@ 是Ptr&lt;A&gt;,以此类推。

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

    【讨论】:

      【解决方案2】:

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

      类类型T必须是完整的,如果:
      — [...]
      — 类成员访问运算符应用于T (5.2.5) 类型的表达式,或
      — [...]

      编写A::ptr 需要A 才能完成。 A 在我们定义 C 的地方并不完整,所以这是一个错误。

      另一方面,当您编写 A* 时,要求 A 是完整的。将指向不完整类型的指针(或引用)作为成员很好。

      【讨论】:

        【解决方案3】:

        我的建议:

        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。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-10-27
          • 1970-01-01
          • 2013-06-13
          • 2018-07-17
          • 2013-10-21
          • 2011-09-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多