我有几个类(FBSDKGraphRequestHandler completionHandler = ^ (FBSDKGraphRequestConnection * connection, id result, NSError * error) {
,A
,B
),每个类都有一个带有模板化(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
答案 0 :(得分:2)
为了解决循环依赖,你只需要给编译器一个手,并传授一些关于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;
}
答案 1 :(得分:1)
某些操作只能在完整类型上执行。其中之一是来自[basic.def.odr]:
如果符合以下条件,则类型
T
必须完整:
- [...]
- 类成员访问运算符应用于类型T
(5.2.5)或
的表达式 - [...]
撰写A::ptr
需要A
完成。在我们定义A
时,C
尚未完成,因此这是一个错误。
另一方面,当您编写A*
时,不需要A
才能完成。将指向不完整类型的指针(或引用)作为成员就可以了。
答案 2 :(得分:1)
我的建议:
稍微更新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。