假设我有两个班级:
class A
{
public:
typedef std::shared_ptr<A> Ref;
...
private:
B::Ref _b;
}
class B
{
public:
typedef std::shared_ptr<B> Ref;
...
private:
A::Ref _a;
}
这显然需要B类和B :: Ref的前向声明。前向声明B很简单,但是如何对B :: Ref也这样做呢?
答案 0 :(得分:8)
解决此问题的方法之一是
class A;
class B ;
template <typename T>
struct Traits {
typedef std::shared_ptr<T> Ptr;
};
class A
{
private:
Traits<B>::Ptr _b;
};
class B
{
private:
Traits<A>::Ptr _a;
};
答案 1 :(得分:4)
您无法转发声明嵌套typedef
,因为在前向声明B
处将是一个不完整的类型。但是,您可以解决以下问题:
class B;
class A {
std::shared_ptr<B> _b;
public:
typedef std::shared_ptr<A> Ref;
};
class B {
A::Ref _a;
public:
typedef std::shared_ptr<B> Ref;
};
答案 2 :(得分:2)
拥有&#34的typedef;这就是你引用对象的方式X
&#34;内部类X
是一个糟糕的设计决策,正是因为您需要X
的完整定义来查看其成员,但您希望能够在没有完整定义的情况下引用X
。
我可以看到解决这个问题的两种方法。一种是放弃范围界定,只需调用typedef RefA
,定义类在前向声明的位置:
class A;
typedef std::shared_ptr<A> RefA;
或者,您可以委派&#34;知道如何参考&#34;到一个单独的班级。你可以把它变成一个类模板,这样类仍然可以在那里注册自己喜欢的引用类型:
template <class T>
struct RefT
{
typedef T *type; // Default reference type
};
template <class T>
using Ref = typename RefT<T>::type;
class A;
template <>
struct RefT<A>
{
typedef std::shared_ptr<A> type;
};
class B
{
private:
Ref<A> _a;
};
答案 3 :(得分:1)
不幸的是,你无法转发声明嵌套的typedef。但是,您可以使用全局typedef,例如
typedef std::shared_ptr<B> RefB ;
等等。其他解决方案是使用后期模板专业化,如下所示:
template <typename T> class BImpl;
template <typename T>
class AImpl
{
public:
typedef std::shared_ptr<AImpl> Ref;
private:
typename BImpl<T>::Ref _b;
};
template <typename T>
class BImpl
{
public:
typedef std::shared_ptr<BImpl> Ref;
typename AImpl<T>::Ref _a;
};
typedef AImpl<void> A;
typedef BImpl<void> B;
答案 4 :(得分:1)
当我想转发typedef时,我总是考虑继承。它看起来像这样:
template<typename T>
class Ref : public std::shared_ptr<T>
{
Ref()
{}
Ref(T *t)
: std::shared_ptr<T>(t)
{}
};
class B;
class A
{
public:
//...
private:
Ref<B> _b;
};
class B
{
public:
//...
private:
Ref<A> _a;
};