[英]Typedefs in circular-dependend classes
我有几个类( A
, B
, C
),每个类都有一个具有模板化( Ptr<...>
)类型的成员,这取决于另一个类(循环)的不完整类型。 我想按如下所示对类型( ::ptr
)进行typedef。 这似乎不起作用–我的编译器告诉我以下内容:
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
为了解决循环依赖的问题,您只需要向编译器伸出援助之手,并对另一个类中的ptr
有所了解,即:您知道A::ptr
是Ptr<A>
,依此类推。
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;
}
您只能对完整类型执行某些操作。 其中之一是,来自[basic.def.odr]:
如果满足以下条件,则类类型
T
必须是完整的:
— [...]
—将类成员访问运算符应用于类型T
(5.2.5)的表达式,或
— [...]
编写A::ptr
要求A
完整。 在定义C
, A
还不完整,所以这是一个错误。
在另一方面,当你写A*
但是,这并不需要A
是完整的。 拥有指向不完整类型的指针(或引用)作为成员很好。
我的建议:
稍微更新P
的定义以定义派生的类型名。
template<class T> class Ptr { public: using ptr_t = T*; ptr_t ptr; };
更新A.hpp,B.hpp和C.hpp分别仅依赖于B
, C
和A
前向声明。
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。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.