35

是否可以前向声明嵌套类,然后将其用作外部类的具体(不是指向/引用)数据成员的类型?

IE

class Outer;

class Outer::MaybeThisWay   // Error: Outer is undefined
{
};

class Outer
{
 MaybeThisWay x;

 class MaybeThatOtherWay;

 MaybeThatOtherWay y;   // Error: MaybeThatOtherWay is undefined
};
4

6 回答 6

39

你不能像这样前向声明一个嵌套类。

根据您要执行的操作,也许您可​​以使用命名空间而不是外层的类。您可以前向声明这样的类没有问题:

namespace Outer {
   struct Inner; 
};

Outer::Inner* sweets;  // Outer::Inner is incomplete so 
                       // I can only make a pointer to it

如果您的 Outer 绝对必须是一个类,并且您不能将它硬塞到命名空间中,那么您需要在转发声明 Inner 的上下文中将 Outer 设为完整类型。

class Outer
{
   class Inner;  // Inner forward-declared
};  // Outer is fully-defined now

Outer yes;  // Outer is complete, you can make instances of it
Outer::Inner* fun;  // Inner is incomplete, you can only make 
                    // pointers/references to it

class Outer::Inner 
{
};  // now Inner is fully-defined too

Outer::Inner win;  // Now I can make instances of Inner too
于 2010-04-08T14:25:13.257 回答
15

如果不完全指定包含类,就无法转发声明嵌套类。这个小技巧有点解决问题

class Outer_Inner
{
};

class Outer
{
public:
   typedef Outer_Inner Inner;
};

这对我有用,因为在我的命名约定Outer_Inner中不是有效的类名,所以很明显它指的是嵌套类。

您仍然不能像这样转发声明嵌套类:

class Outer::Inner;

但至少可以通过以下方式进行前向声明:

class Outer_Inner;

如果您不喜欢 Outer_Inner 的外观,您可以采用更适合您口味的嵌套类的命名约定。 Outer__Inner,Outer_nested_Inner等。

于 2010-04-08T14:50:02.390 回答
1

不,但有什么问题

class Outer {
public:  //or protected or private
    class Inner {
    };

private:
    Inner foo;
};

向前声明在这里没有意义,除非我遗漏了一些东西(这可能是因为你的问题缺乏很多细节)

请记住,如果一个类是前向声明的,那么您只能声明对前向声明类型的对象的引用或指针。你不能用它做任何其他事情,包括访问它的成员或函数。

于 2010-04-08T13:56:07.683 回答
1

如果一个类已被前向声明(但您还没有完整的定义),那么您只能声明一个指向它的指针,因为编译器还不知道类的大小(也不知道其字段的名称或方法)。

于 2010-04-08T13:58:14.187 回答
0

如果您声明类型的属性MaybeThatOtherWay,而不是引用或指针,编译器必须知道类的完整定义以确定外部类的大小。因此,您不能使用前向声明和那种字段声明,无论它是否是嵌套类。

于 2010-04-08T14:05:40.683 回答
0

如果您只需要一个类型作为函数参数或静态变量,则可以在客户端完成。例如,要从 Outer 接收事件通知:

界面:

class Client {
public:
private:
    static void gotIt(int event);
    class Helper;
};

执行:

#include <outer.hpp>

class Client::Helper {
public:
    static void fromOuter(Outer::Inner const& inner) 
    { 
        gotIt(inner.event());
    }
};
于 2015-12-21T17:38:29.403 回答