是否有没有前向声明的不完整嵌套类型的语法?
Is there a syntax for incomplete nested type without a forward declaration?
以下程序产生诊断错误。
#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_; }
//...
};
//...
你应该把那个声明 class Nested;
放在那里。
声明Ptr
和Nested
关系是先有鸡还是先有蛋的问题,前向声明才是正确的处理方式。
编译器需要知道标记 Nested
是一个 class,而不是其他东西。当编译器达到 Ptr
时,该信息就足够了,class 的详细信息尚不相关。然后编译器到达完整的 Nested
声明,详细信息可用于 class.
的所有未来使用
不,没有。
但是,您根本不需要避免前向声明。这有效:
class Containing {
class NestedInterface;
typedef std::shared_ptr<NestedInterface> Ptr;
class NestedObject {
Ptr ptr_;
//...
};
class NestedInterface {
// ...
};
};
有时 classes 内部的交叉依赖性可能会使这很难做到。在这种情况下,您需要做的就是避免定义内联引用 classes,而是声明 other classes 外联,像这样:
class Containing {
class NestedInterface;
class NestedObject;
typedef std::shared_ptr<NestedInterface> Ptr;
};
class Containing::NestedObject {
Ptr ptr_;
//...
};
class Containing::NestedInterface {
};
请注意,一般来说,在 C++ 中,嵌套的 classes 不能像在其他语言中那样随心所欲地使用——您通常可以使用外部 [=23] 实现相同的效果=] 是的,他们这样表现得更好。 (它们不需要外部 class 的定义。)只有在少数情况下它们才是绝对必要的。 (想到 std::allocator<T>::rebind<U>
。)
以下程序产生诊断错误。
#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_; }
//...
};
//...
你应该把那个声明 class Nested;
放在那里。
声明Ptr
和Nested
关系是先有鸡还是先有蛋的问题,前向声明才是正确的处理方式。
编译器需要知道标记 Nested
是一个 class,而不是其他东西。当编译器达到 Ptr
时,该信息就足够了,class 的详细信息尚不相关。然后编译器到达完整的 Nested
声明,详细信息可用于 class.
不,没有。
但是,您根本不需要避免前向声明。这有效:
class Containing {
class NestedInterface;
typedef std::shared_ptr<NestedInterface> Ptr;
class NestedObject {
Ptr ptr_;
//...
};
class NestedInterface {
// ...
};
};
有时 classes 内部的交叉依赖性可能会使这很难做到。在这种情况下,您需要做的就是避免定义内联引用 classes,而是声明 other classes 外联,像这样:
class Containing {
class NestedInterface;
class NestedObject;
typedef std::shared_ptr<NestedInterface> Ptr;
};
class Containing::NestedObject {
Ptr ptr_;
//...
};
class Containing::NestedInterface {
};
请注意,一般来说,在 C++ 中,嵌套的 classes 不能像在其他语言中那样随心所欲地使用——您通常可以使用外部 [=23] 实现相同的效果=] 是的,他们这样表现得更好。 (它们不需要外部 class 的定义。)只有在少数情况下它们才是绝对必要的。 (想到 std::allocator<T>::rebind<U>
。)