以下程序产生诊断错误。
#include <memory>
class Containing {
// class Nested; // [1]: This line seems required.
typedef std::shared_ptr<class Nested> Ptr;
class Nested {
Ptr & ptr ();
void foo (const Ptr &p) {
p->ptr() = ptr()->ptr(); // [2]: Error here without [1]
}
};
};
int main () {}
产生的诊断是:
prog.cpp:8:14: error: invalid use of incomplete type 'class Nested' p->ptr() = ptr()->ptr(); ^ prog.cpp:4:35: error: forward declaration of 'class Nested'` typedef std::shared_ptr<class Nested> Ptr; ^
但是,如果我取消注释前向声明,则编译成功。我相信原因是Nested
在用于shared_ptr<>
时不会嵌套。如果是这样,是否有一种语法可以让shared_ptr<>
知道Nested
是否嵌套而没有前向声明?类似的东西:
class Containing {
typedef std::shared_ptr<class Containing::Nested> Ptr;
//...
这个问题使用一个最小的例子来说明问题。实际结构如下:
class Containing {
typedef std::shared_ptr<class NestedInterface> Ptr;
class NestedObject {
Ptr ptr_;
//...
};
class NestedInterface {
virtual NestedObject & object () = 0;
void foo (const Ptr &p) {
// ...
}
//...
};
class NestedType1 : NestedInterface {
NestedObject obj_;
NestedObject & object () { return obj_; }
//...
};
class NestedType2 : NestedInterface {
Containing &c_;
NestedObject & object () { return c_.nested_object_; }
//...
};
//...
答案 0 :(得分:1)
你应该在那里保留声明class Nested;
。
声明Ptr
和Nested
关系是一个鸡与蛋的问题,前向声明是解决这个问题的正确方法。
编译器需要知道令牌Nested
是一个类,而不是其他东西。在编译器达到Ptr
时,该信息就足够了,并且该类的详细信息尚不相关。然后编译器到达完整的Nested
声明,详细信息可用于该类以后的所有用途。
答案 1 :(得分:1)
没有。
但是,您根本不需要避免前向声明。这有效:
class Containing {
class NestedInterface;
typedef std::shared_ptr<NestedInterface> Ptr;
class NestedObject {
Ptr ptr_;
//...
};
class NestedInterface {
// ...
};
};
有时,类中的交叉依赖可能会使这很难做到。在这种情况下,您需要做的就是避免内联定义引用类,而是将其他类声明为异地,如下所示:
class Containing {
class NestedInterface;
class NestedObject;
typedef std::shared_ptr<NestedInterface> Ptr;
};
class Containing::NestedObject {
Ptr ptr_;
//...
};
class Containing::NestedInterface {
};
请注意,通常,在C ++中,嵌套类不会像在其他语言中那样随意使用 - 通常可以与外部类实现相同的效果,并且它们的行为方式要好得多。 (它们不需要外部类的定义。)只有少数情况下它们是绝对必要的。 (std::allocator<T>::rebind<U>
浮现在脑海中。)