为啥我不能在外部定义嵌套类?
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”作为理论上的单例类。它将代表整个应用程序,它的子系统(或“条”)将在类中定义和实例化一次。我这样做是为了让代码更易于管理。如果有人想到更可行的设计模式,请告诉我!
【问题讨论】:
为什么需要一个代表应用程序的对象?应用程序由它运行这一事实表示。如果代码可以执行,那么您就在应用程序中。我可以理解使用单例来提供对某些特定数据(例如文件系统)的访问,但是使用单例来表示应用程序并没有多大意义。 是的,也许我在一节课上投入了太多。我希望单例确定管理的一件事是所有子系统的启动/关闭和服务(通过start
、end
和update
函数)。这让我倾向于将所有实际的子系统也放入其中,但我可能不应该这样做,因为这会限制代码的使用。
【参考方案1】:
问题出在这里:
class Foo
public:
class Bar;
Bar bar;
;
此时Foo::Bar
是一个不完整的类型。而且您不能声明不完整类型的变量。这与尝试这样做没有什么不同:
class Foo;
Foo foo;
它们都是不允许的,并且出于相同的原因。
您可以将bar
变成某种(智能)指针。但这是解决这个问题的唯一方法。
【讨论】:
“没有必要让它成为一个嵌套类”...当然,Foo::Bar
的所有成员都可以访问Foo
的私有成员。
Ben Voigt 所说的,事实上这是我试图维持这种模式的一个关键原因。基本上,我希望我的所有子系统都能够在位于单例类中时相互交互(请阅读我在操作中的旁注)。也许我可以找到一种方法来使用朋友类并从那里构建它。
实际上,朋友类不会削减它,因为我仍然必须将 foo 的成员指定为 foo.bar1
、foo.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->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。这样就不需要自己处理指针了,只要你的类不再使用它,它就会被释放。以上是关于为啥我不能在外部定义嵌套类?的主要内容,如果未能解决你的问题,请参考以下文章