不允许嵌套类的前置声明的原因是什么?

7

例子:

// can't forward declare with class Foo::Bar

// actual class
class Foo
{
public:
    class Bar // or enum Bar
    {
    }
};

我承认在当前的C++标准下,这是不被允许的,但我无法找到一个不允许它的好理由,特别是在C++0x中,我们现在可以前向声明枚举。我想反对它的一个论点可能是,如果我们前向声明了嵌套类,结果该嵌套类是私有的,那么将不会被允许。但这与在命名空间中前向声明一个类,然后声明它为外部类的嵌套类没有太大区别。编译器只会给出一个错误(可能是类似于前面的声明与此声明不匹配的错误信息)。
那么为什么它真正地不被允许呢?
换句话说(由James McNellis提出),“为什么class Foo :: Bar;没有提供Foo或Bar的定义是不允许的?”
鉴于C++标准委员会通过引入C++0x中的枚举前向声明来减少依赖关系和编译时间的好处,那么这肯定是同样的事情的一部分,对吧?

正如Eric Lippert在回答有关C#的这类问题时多次强调的那样,没有充分的理由,就不会将任何东西放入C#规范中。即使是看似微小的变化,其影响也可能在边缘情况、编译时间等方面产生重大差异,因此每个添加的功能都必须得到证明,并且其收益必须超过成本。而且,我要补充的是,没有“容易”实现的功能。 ;) - shelleybutterfly
@Zach:不,Eric Lippert讨论的是C#。但同样的道理也适用于C++。 - Ben Voigt
@Ben:C#?哇,看看谁在说话。这种语言有很多边角情况会导致奇怪和意外的行为。如果这个Eric先生言行一致,C#现在不会如此丰富和表达自如。 - Zach Saw
2
-1 指的是那些并不是真正问题,而只是为了表达不满情绪而提出的问题。当人们试图回答你的问题时,你变得好斗。stackoverflow 不是辩论论坛,它是一个获取帮助和解答问题的地方。 - shelleybutterfly
2
@shelley:如果有人告诉你“这不可能做到”,你难道不想知道为什么吗? - Zach Saw
显示剩余2条评论
3个回答

9
它不在语言中的原因很简单,就是没有人提出一个好的建议来把它纳入到语言中。功能不会自己包含,必须有人编写并解释其优点以及没有(或非常小的)缺点。
不对枚举进行前向声明(enum x;)的论点只是因为编译器在看到有多少个值之前无法选择适当的枚举变量大小。这个问题已经通过允许为编译器决定大小而得到解决(enum x : int;)。这也已经被实现并显示正常工作,然后进入标准。
请参见http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2764.pdf

3

嵌套类可以使用前置声明:

class Foo
{
public:
    class Bar;
};

class Foo::Bar
{
};

3
是的,但第一个声明必须(与所有成员一样)在包含类定义中。我认为问题实际上是“为什么不允许class Foo :: Bar;而不提供FooBar的定义?”。 - James McNellis
2
@James:好的,这是一个不同的问题,答案是:“编译器如何知道Foo应该是类还是命名空间?” - Ben Voigt
1
@Zach:是的,但编译器如何知道**Foo**是类还是命名空间?你还没有声明Foo,因此它可能是任意一种。 - Nicol Bolas
2
或者更高级的解决方案:class Foo::class Bar; - James McNellis
3
在单个TU中并不太重要,因为namespace x {} class x {};是不合法的,但是在同一个程序的第一个TU中可以有namespace x { class foo { }; },而在第二个TU中可以有class x { class foo { }; };,这两个foo实际上是不同的(这可能违反了ODR;我不认为它会,但我不能100%确定,并且肯定不会在真正的程序中碰运气) 。无论如何,如果这是有效的,则class x :: foo;中的x是命名空间还是类是很重要的(除此之外,两个foo的名称肯定会有所不同)。 - James McNellis
显示剩余6条评论

2

如何声明一个嵌套类的前向声明?为此,您必须声明该嵌套在其中的类。一旦您这样做:

class ClassName {

你已经开始了一个完整的类声明。你不能部分声明一个类; 要么全部都在这里,要么没有。所以,如果外部类必须完全声明,那么提前声明内部类有什么好处呢?

唯一的原因是直到现在枚举类型不能被提前声明,是因为它们的大小由它们的枚举值确定。这就是为什么你必须给它们指定一个显式的大小来提前声明它们。


1
为什么必须声明嵌套类所在的类?在所有可能性中,为什么您选择了一种语法,使得无法前向声明嵌套类? - Zach Saw
1
@Zach Saw,我不是编译器或规范设计师,所以我无法告诉你。我只知道一个功能的好处必须大于它的成本,而且我认为你并没有证明它有用,只是展示了它可能是一个构造。无论如何,stackoverflow不是进行辩论的地方;我只是试图回答你的问题。它很可能没有被包含在内,因为它是一些有限使用的东西,因此没有被考虑,或者因为在设计语言和编译器时其有用性被认为不足以抵消负面影响。故事结束。 - shelleybutterfly
1
@Zach:你没有证明什么。内部类的效用还有待商榷。你所做的只是展示了有人可能想要前向声明它们。这并不能证明它是“有用”的。 - Nicol Bolas
1
@shelley:这是允许的(请参见我的回答)。 - Ben Voigt
1
@Nicol:我的证明==C++标准委员会认识到前向声明枚举的好处,因此这也是其中的一部分。嵌套类是否有用是另一回事。如果它没有用处,为什么要首先将其添加到std中(也许你应该证明这个有用?)??? - Zach Saw
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接