具有所有私有成员的类可以是 POD 类吗?

Posted

技术标签:

【中文标题】具有所有私有成员的类可以是 POD 类吗?【英文标题】:Can a class with all private members be a POD class? 【发布时间】:2011-06-13 08:43:47 【问题描述】:

我之前听说 POD 类型不能有私有数据——但根据 C++0x 草案,我的要求比较宽松(强调我的):

对所有非静态数据成员具有相同的访问控制(第 11 条)

这似乎表明私有数据是可以的,只要它都是私有的。我没有 C++03 的副本可以检查...

那么,WindowsApi::Uuid 会是一个 POD 类吗?

namespace WindowsApi

    class Uuid
    
        union
        
            ::UUID asUuid; //Win32's UUID struct
            unsigned __int64 asInt64s[2];
            unsigned __int32 asInt32s[4];
        ;
    public:
        Uuid() 
        Uuid(::UUID sourceStructure) : asUuid(sourceStructure) 
        operator ::UUID()  return asUuid; 
    ;

【问题讨论】:

【参考方案1】:

我之前听说过 POD 类型不能有私有数据

在 C++03 中,POD 类型不能有私有数据(参见 AndreyT 的回答)。

但是 POD 的定义在 C++0x 中已经改变(参见9/10)。

根据n3225

POD 结构是一个既是普通类又是标准布局类的类,并且没有非 POD 结构、非 POD 联合(或此类类型的数组)。 ... ...

POD 类是一个 POD 结构或 POD 联合的类。

意思是

struct demo

   private:
      int a, b;
;

在 C++0x 中是 POD,因为 demo 既是平凡又是标准布局

标准布局的定义在9/7部分

标准布局类是这样的类:

没有非标准布局类(或此类类型的数组)或引用类型的非静态数据成员, 没有虚函数 (10.3) 和虚基类 (10.1), 对所有非静态数据成员具有相同的访问控制(第 11 条), 没有非标准布局基类, 在最派生类和最多一个基类中没有非静态数据成员 非静态数据成员,或没有具有非静态数据成员的基类,并且 没有与第一个非静态数据成员相同类型的基类。11

.

那么,WindowsApi::Uuid 会是一个 POD 类吗?

不! WindowsApi::Uuid 既不是 C++03 中的 POD,也不是 C++0x 中的 POD。普通类是具有普通默认构造函数 (12.1) 并且可以普通复制的类。 WindowsApi::Uuid 有一个重要的默认构造函数。

那么这个规则在 C++0x 中放宽了吗?

是的! (考虑第 11 条)

还可以查看FAQ entry on Aggregates and PODs

【讨论】:

那么“琐碎”的定义是什么? :) @bdonlan : 普通类是具有普通默认构造函数 (12.1) 并且可轻松复制的类。 @Parasoon:哎呀..忘记了默认的析构函数:P 不是那个意思。 +1【参考方案2】:

C++03 仍然不允许在 POD 类中使用非静态私有或受保护数据。此要求在聚合

的定义中指定

聚合是一个数组或类(第 9 条),没有用户声明的构造函数 (12.1),没有私有或受保护的非静态数据成员(第 11 条),没有基类 (第 10 条),并且没有虚函数(10.3)。

并且 POD 类必须首先是一个聚合。

【讨论】:

那么这个规则在 C++0x 中放宽了? (我在 C++0x 草案中没有看到任何关于 POD 类型定义的聚合)【参考方案3】:

根据我的 n3225 C++0x 草稿,WindowsApi::Uuid 是一个 POD 类。

从第 219 页开始: POD 结构是一个既是普通类又是标准布局类的类,并且没有非 POD 结构、非 POD 联合(或此类类型的数组)类型的非静态数据成员。

平凡类是具有平凡默认构造函数并且可以平凡复制的类:

一般可复制的类是这样的类:

没有重要的复制构造函数 (12.8), 没有重要的移动构造函数 (12.8), 没有重要的复制赋值运算符(13.5.3、12.8), 没有重要的移动赋值运算符(13.5.3、12.8),并且 有一个简单的析构函数 (12.4)。

标准布局类是这样的类:

没有非标准布局类(或此类类型的数组)或引用类型的非静态数据成员, 没有虚函数 (10.3) 和虚基类 (10.1), 对所有非静态数据成员具有相同的访问控制(第 11 条), 没有非标准布局基类, 要么在最派生类中没有非静态数据成员,并且最多有一个具有非静态数据成员的基类,要么没有具有非静态数据成员的基类,并且 没有与第一个非静态数据成员相同类型的基类。

由于WindowsApi 不违反任何这些约束,它将是 C++0x 下的有效 POD 类。正如 AndreyT 所提到的,这是比 C++03 更慷慨的措辞。

【讨论】:

我在该类中看不到任何用户定义的复制构造函数。构造函数和转换操作符组合成一个拷贝构造函数吗? 它没有用户定义的复制构造函数。 ::WindowsApi::Uuid 是我的班级,::UUID 是 Windows 定义的班级。 (注意 Caps 的区别) @Billy :虽然你有一个不平凡的默认构造函数。 WindowsApi::Uuid 不是 POD。 @Billy:谢谢!不知何故,我将 ::UUID 误读为类的名称。我会更新的。 @Prasoon:默认构造函数是可以在没有任何参数的情况下调用的构造函数。唯一定义的构造函数不是一个。

以上是关于具有所有私有成员的类可以是 POD 类吗?的主要内容,如果未能解决你的问题,请参考以下文章

导出的类中可以有私有成员吗? [复制]

访问超类的私有成员

如何访问其子类中的类的私有变量?

有没有办法让 C++ 结构值初始化所有 POD 成员变量?

类的特殊成员

C++ 友元