【问题标题】:Strange Behaviour Class Objects Inside Union联合内的奇怪行为类对象
【发布时间】:2009-12-09 11:17:34
【问题描述】:

你好我想知道下面代码的原因

void main()
{
  class test
  {
    public:
      test(){}
      int k;
  };

  class test1
  {
    public:
      test1(){}
      int k;
  };

  union Test
  {
    test t1;
    test1 t2;   
  };
}

对于上面的代码,它给出了错误“error C2620: union 'Test': member 't1' has user-defined constructor or non-trivial default constructor

class test
{
  public:
  //test(){}
  int k;
};

class test1
{
  public:
  //test()1{}; 
  int k;
};

union Test
{
  test t1;
  test1 t2; 
};

以上,没有错误。

我想知道原因。

在此先感谢您。 :)

【问题讨论】:

  • 由于已经提供了答案,我只想告诉您,您的第一个代码的 main 返回类型错误。 main() 在 C/C++ 中应该总是返回一个“int”。
  • 仅作记录:C++0x 将支持在联合体内具有非平凡构造函数/析构函数的类。
  • 同样在 test1 类中,ctor 被命名为 test 而不是 test1。

标签: c++ unions


【解决方案1】:

根据 C++ 标准(第 9.5.1 节,在其他答案中也引用了):

联合可以有成员函数(包括构造函数和析构函数),但不能有虚函数。联合不应有基类。联合不应用作基类。具有非平凡构造函数、非平凡复制构造函数、非平凡析构函数或非平凡复制赋值运算符的类的对象不能是联合的成员,也不能是此类对象的数组。如果联合包含静态数据成员或引用类型的成员,则程序格式错误。

我首先链接到Wikipedia article about POD types,其中指出:

C++ 中的 POD 类型定义为标量类型或 POD 类。 POD 类没有用户定义的复制赋值运算符,没有用户定义的析构函数,也没有本身不是 POD 的非静态数据成员。此外,POD 类必须是一个聚合类,这意味着它没有用户声明的构造函数,没有私有或受保护的非静态数据,没有基类和虚函数。该标准包括关于 POD 在 C++ 中的行为方式的声明。

在某些情况下,C++ 只允许使用 POD 类型。 例如,C++ 中的联合不能包含具有虚函数或非平凡构造函数或析构函数的类。施加此限制是因为编译器无法知道应为联合调用哪个构造函数或析构函数。

第二段的第一句话可能会让你认为 C++ 只允许 POD 类型成为联合的一部分。情况并非如此,因为它允许具有私有成员的类成为联合的一部分:

#include <iostream>
using namespace std;

class test1
{
  int i;
};

class test2
{
  int i;
};

union test
{
  test1 t1;
  test2 t2;
};

int main()
{
  cout << __is_pod(test1) << endl;
  cout << __is_pod(test2) << endl;
  cout << __is_pod(test) << endl;

  return 0;
}

上面用MSVC++编译的程序打印出来:

0
0
1

【讨论】:

  • @Gregory:忽略我之前的评论,因为我现在对此不太确定。这就是我对这种情况的看法:标准(在 9.5.1 中)没有明确禁止联合中的非 POD 类型,而是禁止具有非平凡构造函数/析构函数/赋值运算符的类型。这个定义在一定程度上肯定与 POD 重叠,但是 POD 的定义也禁止私有成员变量,据我所知,这些变量并没有被排除在联合之外。因此,工会似乎允许某些非 POD。但同样,我对此并不完全确定。
  • 确实,union 与具有私有成员变量的类型一起工作,尽管这些不会被视为 POD
  • @Charles:具有私有成员属性和普通构造函数的类是有问题的(成员将未初始化),所以我真的想不出一个适用的真实示例
  • @dribeas:是的,这很奇怪。但是非 POD 类仍然可以具有使用这些私有成员变量的成员函数。
  • 这对 C++11 有效吗?@GregoryPakosz
【解决方案2】:

C++ 标准对可以放在联合中的数据类型进行了某些限制。在 9.5.1 中,标准如下:

一个对象 具有非平凡构造函数的类, 一个重要的复制构造函数,一个 非平凡的析构函数,或 非平凡的复制赋值运算符 不能是工会的成员,也不能 一组这样的对象。如果工会 包含静态数据成员,或 引用类型的成员, 程序格式不正确。

所以你的程序不能工作,因为你明确定义了一个构造函数,因此你的对象违反了非平凡的构造函数限制。

【讨论】:

    【解决方案3】:

    在 C++ 中,联合可能不包含具有(非平凡)构造函数或析构函数的类。这是因为编译器无法告诉在创建或销毁联合实例时使用哪个构造函数或析构函数。

    【讨论】:

      猜你喜欢
      • 2014-02-20
      • 1970-01-01
      • 1970-01-01
      • 2011-02-08
      • 1970-01-01
      • 2021-01-24
      • 1970-01-01
      • 2014-07-17
      • 2010-12-06
      相关资源
      最近更新 更多