C++ 作为基类的并集

C++ 作为基类的并集,c++,inheritance,unions,language-lawyer,C++,Inheritance,Unions,Language Lawyer,该标准定义了不能将联合用作基类,但对此有什么具体的理由吗?据我所知,联合可以有构造函数、析构函数、成员变量和方法来操作这些变量。简言之,联合可以封装可能通过成员函数访问的数据类型和状态。因此,在最常见的术语中,它有资格成为一个类,如果它可以充当一个类,那么为什么它被限制作为基类呢 编辑:虽然答案试图解释推理,但我仍然不明白,作为派生类的Union如何比作为一个类的Union更糟糕。因此,为了得到更具体的答案和理由,我将推动这一个悬赏。对已经发布的答案没有冒犯,谢谢 Union是一种类型,可以用作

该标准定义了不能将联合用作基类,但对此有什么具体的理由吗?据我所知,联合可以有构造函数、析构函数、成员变量和方法来操作这些变量。简言之,联合可以封装可能通过成员函数访问的数据类型和状态。因此,在最常见的术语中,它有资格成为一个类,如果它可以充当一个类,那么为什么它被限制作为基类呢


编辑:虽然答案试图解释推理,但我仍然不明白,作为派生类的Union如何比作为一个类的Union更糟糕。因此,为了得到更具体的答案和理由,我将推动这一个悬赏。对已经发布的答案没有冒犯,谢谢

Union是一种类型,可以用作其任何一个成员,具体取决于已设置的成员-以后只能读取该成员

从类型派生时,派生类型将继承基类型-无论基类型位于何处,都可以使用派生类型。如果可以从联合派生,则派生类可以在任何可以使用联合成员的地方使用(不是隐式使用,而是通过命名成员显式使用),但在这些成员中,只能合法访问一个成员。问题是已设置成员的数据未存储在联合中


<>避免这种微妙而危险的矛盾,实际上是一个不允许从一个联合体派生的类型系统。

< P > Bjarne Stroustrup在注释的C++参考手册中说“似乎没有什么原因。”< P> > P>这是我对C++ 03的猜测。

> $5//1,在C++ 03中,联合不能具有虚拟函数。有意义的派生的全部要点是能够重写派生类中的行为。如果一个并集不能有虚函数,这意味着从并集派生没有意义


因此就有了规则。

标题问为什么联合不能成为基类,但问题似乎是关于联合作为派生类的问题。那么,是哪一个

没有技术上的理由说明工会不能成为基类;这是不允许的。一个合理的解释是把联盟看作一个结构,它的成员在内存中可能发生重叠,并将派生类视为继承自这个(相当奇怪)结构的类。如果需要该功能,通常可以说服大多数编译器接受匿名联合作为结构的成员。下面是一个适合用作基类的示例。(联盟中有一个匿名结构,这是一个很好的衡量标准。)

将联合作为派生类的理由可能更简单:结果不会是联合。工会必须是其所有成员和所有基础的工会。这很公平,可能会打开一些有趣的模板可能性,但您会有一些限制(所有基和成员都必须是POD——并且您能够继承两次吗,因为派生类型本质上是非POD的?),这种继承类型将不同于语言中的另一种类型(好吧,这并不是以前停止C++),它还是多余的——现有的联合功能也可以。

Stroustrup在D&E书中说:

void*
一样,程序员应该知道联合……具有内在的危险性,应该尽可能避免,并且在实际需要时应特别小心处理

(省略不会改变意思。)


<> P>所以我认为这个决定是任意的,他没有看到任何理由改变联盟功能(它与C++的C子集一样好,所以没有设计任何与C++新的特征相结合的东西。当风变了,它就被卡住了。

< P>我在你对EJP的回答的评论中自己得到了答案。< /P> 我认为工会只包含在C++中,以便与C兼容。我猜在1970,工会似乎是个好主意,在有微小内存空间的系统上。到C++出现的时候,我想工会已经显得不那么有用了。
考虑到工会是非常危险的,也不是非常有用,从工会继承而来的大量创造bug的新机会似乎不是一个好主意:-)

托尼·帕克给出了一个非常接近事实的答案。C++委员会基本上不认为将工会作为C++的强大部分是值得的,类似于将数组处理为必须继承的C,但实际上并不需要。 联合体存在问题:如果我们允许联合体中使用非POD类型,那么如何构造它们?这当然可以做到,但不一定安全,任何审议都需要委员会的资源。最终的结果并不令人满意,因为在一种理智的语言中,真正需要的是歧视性的结合,而简单的C结合永远不可能以与C兼容的方式提升为歧视性的结合(无论如何,我可以想象)

详细说明技术问题:由于您可以在结构中封装POD组件的唯一联合,而不会丢失任何东西,因此允许联合作为基础没有任何优势。对于POD-only联合组件,显式构造函数只需分配一个组件,也不需要为编译器生成的复制构造函数(或赋值)使用bitblit(memcpy)

<> P>这样的联盟,除了保留它们之外,没有足够的用处,所以现有的C代码可以被认为是有效的C++。这些只有POD的联盟在C++中被破坏,因为它们不能保留C中拥有的重要不变量:任何数据类型都可以用作组件类型。 为了使联合变得有用,我们必须允许可构造的类型作为成员。这很重要,因为我无法接受
struct V3 {
    union {
        struct {
            float x,y,z;
        };
        float f[3];
    };
};
union X { string a; string b; X(string q) : a(q) {} };
#include <cstddef>

template <size_t N,typename T>
struct VecData {
  union {
    struct {
      float x;
      float y;
      float z;
    };
    float a[N];
  };
};

template <size_t N, typename T>
  class Vec : public VecData<N,T> {
    //methods..
};