循环依赖中的 Typedef 类
Typedefs in circular-dependend classes
我有几个 classes (A
, B
, C
) 每个都有一个模板化 (Ptr<...>
) 类型的成员关于另一个class(循环)的不完整类型。我想对类型 (::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
有些操作只能对完整类型执行。其中之一是,来自 [basic.def.odr]:
A class type T
must be complete if:
— [...]
— a class member access operator is applied to an expression of type T
(5.2.5), or
— [...]
写入 A::ptr
需要 A
才能完成。 A
在我们定义 C
的地方不完整,所以这是一个错误。
另一方面,当您写 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。
为了解决循环依赖,您只需要帮助编译器并预知 ptr
将在另一个 class 中发生什么,即:你知道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;
}
我有几个 classes (A
, B
, C
) 每个都有一个模板化 (Ptr<...>
) 类型的成员关于另一个class(循环)的不完整类型。我想对类型 (::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
有些操作只能对完整类型执行。其中之一是,来自 [basic.def.odr]:
A class type
T
must be complete if:
— [...]
— a class member access operator is applied to an expression of typeT
(5.2.5), or
— [...]
写入 A::ptr
需要 A
才能完成。 A
在我们定义 C
的地方不完整,所以这是一个错误。
另一方面,当您写 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。
为了解决循环依赖,您只需要帮助编译器并预知 ptr
将在另一个 class 中发生什么,即:你知道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;
}