为啥我不能在外部定义嵌套类?

Posted

技术标签:

【中文标题】为啥我不能在外部定义嵌套类?【英文标题】:Why can't I define a nested class externally?为什么我不能在外部定义嵌套类? 【发布时间】:2011-09-25 18:32:27 【问题描述】:

我在使用 MinGW C++ 组合一个涉及嵌套类的对象模型时遇到了麻烦。这是一个暴露我的问题的示例:

foo.h:

/*
 * foo.h
 *
 *  Created on: Sep 25, 2011
 *      Author: AutoBot
 */

#ifndef FOO_H_
#define FOO_H_

class Foo

public:
    class Bar;
    Bar bar;
 extern foo;


#endif /* FOO_H_ */

bar.h:

/*
 * bar.h
 *
 *  Created on: Sep 25, 2011
 *      Author: AutoBot
 */

#ifndef BAR_H_
#define BAR_H_

#include <iostream>
using namespace std;

#include "foo.h"

class Foo::Bar

public:
    void Test() cout <<"Test!";
;


#endif /* BAR_H_ */

main.cpp:

/*
 * main.cpp
 *
 *  Created on: Sep 25, 2011
 *      Author: AutoBot
 */



#include "foo.h"

Foo foo;

int main (int argc, char *argv[])

    foo.bar.Test();
    return 0;

Eclipse CDT 构建日志:

**** Build of configuration Debug for project NestedClassTest ****

**** Internal Builder is used for build               ****
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o src\main.o ..\src\main.cpp
In file included from ..\src\main.cpp:10:0:
..\src\/foo.h:15:6: error: field 'bar' has incomplete type
..\src\main.cpp: In function 'int main(int, char**)':
..\src\main.cpp:16:6: error: 'class Foo' has no member named 'bar'
Build error occurred, build is stopped
Time consumed: 171  ms.

所以本质上它无法识别我在 bar.h 中创建的 bar 的定义。这是正常的吗?为什么我不能以这种方式定义嵌套类?这仅仅是 MinGW 工具链的限制吗?感谢您提供任何帮助/建议。

旁注:在我的实际程序中,我打算将它的“foo”作为理论上的单例类。它将代表整个应用程序,它的子系统(或“条”)将在类中定义和实例化一次。我这样做是为了让代码更易于管理。如果有人想到更可行的设计模式,请告诉我!

【问题讨论】:

为什么需要一个代表应用程序的对象?应用程序由它运行这一事实表示。如果代码可以执行,那么您就在应用程序中。我可以理解使用单例来提供对某些特定数据(例如文件系统)的访问,但是使用单例来表示应用程序并没有多大意义。 是的,也许我在一节课上投入了太多。我希望单例确定管理的一件事是所有子系统的启动/关闭和服务(通过startendupdate 函数)。这让我倾向于将所有实际的子系统也放入其中,但我可能不应该这样做,因为这会限制代码的使用。 【参考方案1】:

问题出在这里:

class Foo

public:
    class Bar;
    Bar bar;
;

此时Foo::Bar 是一个不完整的类型。而且您不能声明不完整类型的变量。这与尝试这样做没有什么不同:

class Foo;
Foo foo;

它们都是不允许的,并且出于相同的原因。

您可以将bar 变成某种(智能)指针。但这是解决这个问题的唯一方法。

【讨论】:

“没有必要让它成为一个嵌套类”...当然,Foo::Bar 的所有成员都可以访问Foo 的私有成员。 Ben Voigt 所说的,事实上这是我试图维持这种模式的一个关键原因。基本上,我希望我的所有子系统都能够在位于单例类中时相互交互(请阅读我在操作中的旁注)。也许我可以找到一种方法来使用朋友类并从那里构建它。 实际上,朋友类不会削减它,因为我仍然必须将 foo 的成员指定为 foo.bar1foo.bar2 等......(而不仅仅是 bar1 和 @987654330 @)。我使用了 Nicol Bolas 的指针想法,经过一些调整,它似乎可以工作。如果指针不会给我带来太多麻烦,我将继续追求这个对象模型。我确实明白,在评估 bar 时,它是不完整的,但我想不幸的是,我必须因此而求助于指针。无论哪种方式,它现在都有效。谢谢! @BenVoigt 糟糕,我忘记了。已编辑。 @AutoBotAM 类不应随意访问彼此的隐私。甚至同一子系统中的类。这违背了封装的全部目的:合理保证可以影响一个状态的函数的数量是有限的。你正在做的事情不能做到这一点。【参考方案2】:

您在这里遇到的一个问题是,当您这样做时:

class Foo

public:
    class Bar;
    Bar bar;
 extern foo;

Bar bar 是非法的,因为您尝试使用提供不完整类型的class bar;

你也不包括 Bar.h

【讨论】:

如果我将Bar bar 更改为Bar *bar (foo.h),添加#include "foo.h" (bar.h),并将foo.bar.Test() 更改为foo.bar-&gt;Test() (main.cpp),我得到两个错误:..\src\/bar.h:16:7: error: 'Foo' has not been declared..\src\/bar.h:17:1: error: expected unqualified-id before '' token 所以看起来 bar 已经正确初始化了,但是现在 Bar 看不到 Foo! xD 只有在 main.cpp 中也包含 bar.h 并从 bar.h 中删除包含 foo.h 时才有效。 好的,我已经做到了,现在看来可以了!如果指针不会造成太多麻烦,我会继续追求这个对象模型。谢谢! 我建议你对 Bar 实例使用一些 std::shared_ptr 或 boost::shared_ptr。这样就不需要自己处理指针了,只要你的类不再使用它,它就会被释放。

以上是关于为啥我不能在外部定义嵌套类?的主要内容,如果未能解决你的问题,请参考以下文章

为啥嵌套的子类可以访问其父类的私有成员,而孙子却不能?

为啥不能推导出嵌套在模板类中的枚举的模板参数?

为啥嵌套函数可以从外部函数访问变量,但不允许修改它们[重复]

静态内部类(静态嵌套类或嵌套类)

为啥嵌套的 using 块会多次处理对象? [复制]

JAVA中的内部类