C++ 循环依赖类中的typedef

C++ 循环依赖类中的typedef,c++,class,templates,typedef,circular-dependency,C++,Class,Templates,Typedef,Circular Dependency,我有几个类(a,B,C),每个类都有一个模板化(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
B
C
),每个类都有一个模板化(
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
#如果NDEF测试包括
#定义测试包括1
甲级;
#包括“B.hpp”
#包括“P.hpp”
甲级{
公众:
typedef-Ptr-Ptr;
B::ptrb;
};
#恩迪夫
B.水电站:

#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
#如果NDEF测试包括
#定义测试包括1
乙级;;
#包括“C.hpp”
#包括“P.hpp”
B类{
公众:
typedef-Ptr-Ptr;
C::ptr-C;
};
#恩迪夫
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
\ifndef测试包括
#定义测试\u包括\u C 1
丙级;;
#包括“A.hpp”
#包括“P.hpp”
C类{
公众:
typedef-Ptr-Ptr;
A::ptr A;
};
#恩迪夫
p.hpp:

#ifndef TEST_INCLUDE_PTR
#define TEST_INCLUDE_PTR 1

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

#endif
\ifndef测试\u包括\u PTR
#定义测试包括测试1
模板
类Ptr{
公众:
T*ptr\T;
};
#恩迪夫

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

如果:
-[…]
-类成员访问运算符应用于类型为
T
(5.2.5)或
-[……]

编写
A::ptr
需要
A
才能完成<在定义
C
时,code>A不完整,因此这是一个错误


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

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

如果:
-[…]
-类成员访问运算符应用于类型为
T
(5.2.5)或
-[……]

编写
A::ptr
需要
A
才能完成<在定义
C
时,code>A不完整,因此这是一个错误

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

我的建议:

  • 稍微更新
    p
    的定义,以定义派生类型名

    template<class T>
    class Ptr {
    public:
        using ptr_t = T*;
        ptr_t ptr;
    };
    
    同样地更新B.hpp和C.hpp

  • 我的建议是:

  • 稍微更新
    p
    的定义,以定义派生类型名

    template<class T>
    class Ptr {
    public:
        using ptr_t = T*;
        ptr_t ptr;
    };
    
    同样地更新B.hpp和C.hpp


  • 为了解决循环依赖关系,您只需要帮助编译器,并预先了解另一个类中的
    ptr
    是什么,即:您知道
    a::ptr
    ptr

    A类;
    乙级;;
    模板
    结构Ptr{T*Ptr_T;};
    甲级{
    公众:
    使用ptr=ptr;
    ptrb;
    };
    B类{
    公众:
    使用ptr=ptr;
    Ptr-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;
    }
    
    为了解决循环依赖关系,您只需要帮助编译器,并传授另一个类中
    ptr
    的一些预先知识,即:您知道
    a::ptr
    ptr

    A类;
    乙级;;
    模板
    结构Ptr{T*Ptr_T;};
    甲级{
    公众:
    使用ptr=ptr;
    ptrb;
    };
    B类{
    公众:
    使用ptr=ptr;
    Ptr-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;
    }
    
    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;
    }