在C ++中,有可能有一个类继承自其成员类之一吗? [英] In C++, is it possible to have a class inherit from one of its member classes?

查看:161
本文介绍了在C ++中,有可能有一个类继承自其成员类之一吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的代码不编译,因为编译器不知道 foo :: bar 是什么时遇到它。

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



有没有办法编译这个代码(或其某些变体)?

解决方案

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



虽然问题的形式看起来是非常规的,但是问题是完全线性的:因为递归是某些编程范式背后的原语之一(C ++声称支持,像函数范式),if函数允许递归(直接或间接),为什么它不能应用于数据定义?



毕竟,如果有什么问题是可能的一个宇宙的有趣的功能在元编程领域中开放:当通用traits类被用作在通用状态之上定义通用算法的通用类的类型生成器时,具有这样的构造函数可以允许(除其他之外)将类型生成器转换为泛型类本身,简化了整体参数化,导致完全不同的方式来处理通用算法和他们的渐进的部分专业化。



是不可能的,是C ++编译器,必须支持独立的翻译单元(编译后链接),并且必须支持非正交语法(这被称为不可判定的语法问题)。



由于这两个事实,C ++不能有一个纯递归全局解析器。你不能使用未知符号,让该符号的关联具体发生,因为解释该符号出现的表达式的方式取决于符号本身的性质: a< b> c 是变量的声明,还是涉及变量的表达式?你不知道你不知道a和b是否是变量或类型。



由于符号的性质是编译器内部状态,因此不能使用 foo :: bar 因为它是一个类(像一个基础形成一个派生的)之前知道它真的是一个类(而不是一个变量或其他)。但这只会在以后发生(当 class bar 声明被满足时)。



这是导致有前向声明的相同原因,声明与定义分开: a 如果至少 a 不知道是可调用目的。如果 a 是函数,至少当满足 a(b)时,

但在你的情况下,没有办法预期 foo :: bar 声明是bar声明,保留在foo定义。



为了找到解决方案,语言应该支持



  1:class foo; //我们知道foo是一个类
2:class foo :: bar; //我们知道bar是foo范围内的类

3:class foo :: bar
{
...
}; //我们知道这里foo :: bar的宽度是

4:class foo:public foo :: bar //我们必须知道foo :: bar width here ...
{
...
}; // ...总结foo大小。

这里的问题是 2:不合法C ++:编译器还没有看到 bar 符号,在它之前有单词 class



但这需要

  class foo 
{
class bar;
};

已存在。但是如果你让它存在,你不能再声明 class foo:public bar {...};

$



换句话说,您在语法中遇到非正交。关键是它不会被解决,因为围绕这种不一致性已经部署了一些编程范例,不需要该构造工作,并已经做了足够的洗脑,让sooo许多人(只是看看评论你问和大多数的答案)让他们拒绝的想法,甚至在试图了解之前,如果它可以是有用的东西。他们只是说我不喜欢这个,因为我只有别的东西,可以打扰我。试图找到虚假的隐喻来支持动机 - 完全驻留在旧的C编译模型C ++仍然必须处理。


The following code doesn't compile because the compiler doesn't know what foo::bar is when it encounters it.

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

Is there any way to make this code (or some variation of it) compile?

解决方案

I don't know why, but I find this question very interesting. Especially seeing how many answer try not to give a technical reason why the language don't allow this, but try to convince the author about the "ugliness" of such a definition (tha's ultimately a subjective matter).

Although the form of the question looks unconventional, what is asking is perfectly linear: since recursion is one of the primitives behind certain programming paradigms (that C++ claim to support, like the functional paradigm), if functions are allowed to be recursive (either directly or indirectly) why the same cannot apply to data definitions?

After all, if what is asked is possible a universe of interesting features opens in the area of meta-programming: when a generic traits class is used as a type generator for a generic class defining generic algorithms on top of a generic state, having a constructor like that can allow (among other things) to place the type generator into the generic class itself, simplifying the overall parametrization, leading to a completly different way to approach the generic algorithms and their "progressive partial specialization".

The rereason why this is not possible, is that C++ compilers, have to support independent translation units (that links after compilation), and have to support a non-orthogonal grammar (this is know as the "undecidable syntax problem").

Because of those two facts together, C++ cannot have a pure recursive global parser. You cannot use "unknown symbols" letting the association of that symbol to something concrete to happen later because the way to interpret the expression that symbol appears in, depends on the nature of that symbol itself: a<b>c is declaration of a variable, or an expression involving variables? You cannot know if you don't know if a and b are variables or types.

And since the "nature of a symbol" is "compiler internal state", you cannot use foo::bar as it is a class (like as a base to form a derived one) before knowing it really IS a class (and not a variable or something else). But this happens only later (when the class bar declaration is met).

This is the same reason that lead to have forward declarations, and declaration separated from definitions: a(b) cannot be transalted if at least a is not known to be a "callable object". If a is function, at least its prototype must be known when a(b) is met.

But in your case there is no way to anticipate the foo::bar declaration being the bar declaration to stay inside the foo definition.

To come to a solution the language should support someting like

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.

The problem, here, is that 2: is not legal C++: the compiler has not yet seen the bar symbol alone, with the word class before it.

But this requires

class foo
{
  class bar;
};

to already exist. But if you make that to exist you cannot anymore declare class foo: public bar {...}; later.

In other words, you meet an non-orthogonality in the grammar. The point is that it will not be solved, since around this inconsistency there have been deployed a number of programming paradigms that does not require that construct to work, and have already make enough brainwashing to let sooo many people (just look at the comments in you question and under the most of the answers) the let them to just refuse the idea even before trying to understand if it can be useful to something. They just say "I don't like that something, since I just have something else to like, and that can disturb me. And try to find false metaphors to support motivations that -ultimately- reside in the old C compilation model C++ still has to deal with.

这篇关于在C ++中,有可能有一个类继承自其成员类之一吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆