以下代码无法编译,因为编译器在遇到foo::bar时不知道它是什么。

class foo : foo::bar {
    class bar {
    }
}

有什么办法可以编译此代码(或其某些变体)?

最佳答案

我不知道为什么,但是我觉得这个问题很有趣。尤其是看到有多少答案试图不给出语言不允许这样做的技术原因,而是试图说服作者这种定义的“丑陋”(最终是主观的)。

尽管问题的形式看起来是非常规的,但提出的问题却是完全线性的:由于递归是某些编程范例(C++声称支持的范例,如功能范例)背后的原语之一,因此,如果允许函数递归的话(直接或间接)为什么同样不能应用于数据定义?

毕竟,如果提出的要求是可能的,那么在元编程 Realm 就会打开一个有趣的功能范围:当将通用特征类用作通用类的类型生成器时,该通用类在通用状态之上定义通用算法,这样的构造函数可以(除其他事项外)将类型生成器放置到泛型类本身中,从而简化整体参数化过程,从而提供一种完全不同的方式来处理泛型算法及其“渐进式局部特化”。

原因之所以如此,是因为C++编译器必须支持独立的翻译单元(在编译后链接),并且必须支持非正交语法(这被称为“不确定语法问题”)。

由于这两个事实,C++不能具有纯递归全局解析器。您不能使用“未知符号”来使该符号与具体事物的关联在以后发生,因为解释该符号出现的表达式的方式取决于该符号本身的性质:a<b>c是变量的声明,或表达式涉及变量?您无法确定a和b是变量还是类型。

而且,由于“符号的性质”是“编译器内部状态”,因此您不能使用foo::bar,因为它是一类(例如作为形成派生类的基础)作为,然后才知道它实际上是类(而不是变量)或者是其他东西)。但这只会在以后发生(当满足类栏声明时)。

这与导致具有前向声明以及声明与定义分开的原因相同:如果至少不知道a(b)是“可调用对象”,则a不能被转换。如果a是函数,则在满足a(b)时至少必须知道其原型(prototype)。

但是在您的情况下,无法预期foo::bar声明为bar声明会保留在foo定义内。

要提出解决方案,该语言应支持诸如

1: class foo; //we know foo is a class
2: class foo::bar; // we know bar is a class inside foo scope

3: class foo::bar
   {
     ...
   }; //we know here how wide foo::bar is

4: class foo: public foo::bar // we must know about foo::bar width here...
   {
     ...
   }; //... to sum up the foo size.

这里的问题是2:不是合法的C++:编译器尚未单独看到bar符号,其前面带有单词class

但这需要
class foo
{
  class bar;
};

已经存在。但是,如果使它存在,就无法在以后声明class foo: public bar {...};

换句话说,您在语法中遇到了非正交性。关键是它不会得到解决,因为围绕这种不一致之处,已经部署了许多编程范式,这些范式不需要该构造起作用,并且已经进行了足够的洗脑,以至于让很多人(只需看一下您提出问题并根据大多数答案进行回答),让他们甚至在试图理解该想法是否对某些事情有用之前就拒绝该想法。他们只是说:“我不喜欢那样的东西,因为我还有其他喜欢的东西,这可能会打扰我。并尝试找到错误的隐喻,以支持动机-最终-仍然存在于旧的C编译模型中,C++仍然处理。

关于c++ - 在C++中,是否可以使一个类从其成员类之一继承?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19923100/

10-16 11:30