为什么没有std :: is_structtypes的特征?

我已经看到,为了检查typesT是否是我可以使用的类:

 bool isClass = std::is_class<T>::value; 

它对于类和结构都返回true。 我知道在C ++中它们几乎是一样的,但是我想知道为什么在types特征中它们之间没有区别。 检查这种差异总是无用的,还是有更多的理由我不明白?

它对于类和结构都返回true。 我知道在C ++中它们几乎是一样的,但我想知道为什么在types特征中它们之间没有区别。

不幸的是,这是C ++中常见的误解。 有时候是由于根本的误解,但有时候则是由于英语含糊不清。 它可能来自不正确的编译器诊断,写得不好的书,不正确的答案…

你可能读过这样的东西:

除了成员和基础的默认可见性以外,结构和类之间的C ++没有区别。“

这段话可以解释为误导,因为当使用“无差别”这样的短语时, 身份平等的概念很难区分。

事实上,C ++自1985年以来就没有结构。它只有类。

您使用关键字class和关键字struct声明的types是 。 期。 关键字struct和使用该关键字定义类时默认的可见性规则,只是为了与C …的向后兼容性而保留,但这是一种语法。 它不会使得到的types实际上是另一种types。

types特征没有区别,因为从字面上看,并不是一个人做的。

这是不可能区分空义定义的语义差异

 class C { public: }; 

 struct S { }; 

或类似地

 class C { }; 

 struct S { private: }; 

除了struct vs class关键字之外,没有可检测到的行为差异。 另请参阅本问答 。

注意 :正如@KyleStrand所述,派生也需要显式的访问说明符,所以S : private Base {};C : Base {}; 相当于S : Base {};C : public Base {}; ,其中S是一个结构, C是一个类, Base可以是。

他们是一样的东西。 唯一的区别(默认成员可见性)仅在编译时存在。 structclass之间没有任何区别。

ETA:你可能想要的是std::is_pod ,它会告诉你,如果你的类是一个“普通的旧数据types”。 关于这个问题的大部分讨论和评论似乎表明,这就是那些认为应该有区别的人真正想要的。

其他人已经正确指出,在C ++中,除了成员可见性的区别之外,关键字structclass具有相同的含义。

无论你调用聚合types如此定义的“结构”或“类”或“weiruewzewiruz”取决于你。 为了沟通,通常build议遵循既定的惯例,所以我build议反对“weiruewzewiruz”。

也build议使用语义差异作为选词的指导原则。 对于没有很多内部逻辑和不variables的简单聚合数据, struct的使用更为普遍; 一个典型的用法是struct point { float x; float y; }; struct point { float x; float y; }; 。 这种types在文献中通常被称为“结构”或“结构”。 如果有人在C ++中使用fprintf将第一个参数称为“指向FILE结构体的指针”,那就不足为奇了。 FILE是斯科特·迈耶斯(Scott Meyers)在“更高效的C ++”中所expression的一个例子,项目34:

可以肯定的是,两种编译器都可以用同样的方式来devise一个两种语言编译的结构定义[C和C ++ -pas]。

关于自然语言,单词select“结构”并不是巧合:Meyers谈论的是一种普通的旧数据集合,它在两种语言中都具有相同的语义,直到位级。

关于编程语言,所讨论的数据集合的C ++定义是否使用关键字structclass (具有公共访问说明符)并不重要。 struct也许是更自然的select,因为聚合的C ++语义是C结构的语义。 此外,使用struct使C和C ++源更容易共享一个types定义。

C ++标准使用自然语言和编程语言中的“struct”和“structure”,不仅在互操作性的情况下:1.7 / 5:“声明为”或3.2 / 4 struct X; // declare X as a struct type struct X; // declare X as a struct type 。 最有趣的是9/8,为互操作标准奠定基础:

8一个标准布局结构是一个用class-key结构或class-key类定义的标准布局类。 […]

读者如何能够声称C ++中没有结构是超越我的。 这显然不是编辑错误,因为术语“结构”和“类”是相互关联明确设置的。


然而,比单词select和味道更有趣的是明显的,可检验的差异。 在什么情况下C ++聚合可以和C struct相媲美? 也许这个问题是你的问题的基础? 报价中提到的标准布局是标准。 它在9/7详细说明,并基本上规定了这一点

  • inheritance层次结构中只有一个类可能具有非静态数据成员定义(可能是因为标准不希望指定在这样的层次结构中定义在不同级别的数据元素的顺序);
  • 没有虚拟函数或虚拟基类是允许的(因为运行时信息需要额外的实例数据);
  • 所有成员都具有相同的“访问控制”(公开的,受保护的或私有的;可能是因为实现可以通过访问控制来自由订购)。

标准然后说

9 [注:标准布局类对于用其他编程语言编写的代码进行通信非常有用。 它们的布局在9.2中指定。

当然,用C编译的结构定义符合这些标准,因此Scott Meyers断言。 stdio.h中的FILE是一个显着的,不是很平凡的例子。 请注意,该标准并没有做出保证,因为对象布局是依赖于实现的,并且可能只是通过编译器选项而改变。

类是否具有标准布局可以使用typestrait std::is_standard_layout<T>进行testing。 下面的程序,受到cppreference示例的启发,检查标准中列出的主要案例。

 #include <cstdio> #include <typeinfo> #include <type_traits> using namespace std; struct funcOnlyT // fine { int f(); }; class podT { // "class" is ok int m1; int m2; }; struct badAccessCtrlT { // bad: public/private int m1; private: int m2; }; struct polymorphicT { // bad: polymorphic int m1; int m2; virtual void foo(); }; struct inheritOkT: podT // ok: inheritance, data only on one level { int f(); }; struct inheritPlusDataT: podT // bad: inheritance, data on 2 levels { int m3; }; template<typename T1, typename T2> struct templT // ok with std layout types T1, T2 { T1 m1; T2 m2; }; // print type "name" and whether it's std layout template<typename T> void printIsStdLayout() { printf("%-20s: %s\n", typeid(T).name(), std::is_standard_layout<T>::value ? "is std layout" : "is NOT std layout"); } int main() { printIsStdLayout<funcOnlyT>(); printIsStdLayout<podT>(); printIsStdLayout<badAccessCtrlT>(); printIsStdLayout<polymorphicT>(); printIsStdLayout<inheritOkT>(); printIsStdLayout<inheritPlusDataT>(); printIsStdLayout<templT<int, float> >(); printIsStdLayout<FILE>(); } 

示例会话:

 $ g++ -std=c++11 -Wall -o isstdlayout isstdlayout.cpp && ./isstdlayout 9funcOnlyT : is std layout 4podT : is std layout 14badAccessCtrlT : is NOT std layout 12polymorphicT : is NOT std layout 10inheritOkT : is std layout 16inheritPlusDataT : is NOT std layout 6templTIifE : is std layout 9__sFILE64 : is std layout 

C ++ 11§9/ 8 ([class] / 8)

标准布局结构是用类关键字 struct类关键字 class定义的标准布局class标准布局联合是用 union 定义的标准布局类。

C ++ 11§9/ 10 ([class] / 10)

一个POD结构是一个非联合类,既是一个普通的类,也是一个标准的布局类,没有types非POD结构,非POD联合(或这种types的数组)的非静态数据成员。 […]

由于POD结构是标准布局类,因此它是标准布局结构的子集。 据我所知,这是C ++标准中结构的最一般意义。 所以大概你在寻找的是一种types特征或者一组types特征,它们可以让你识别标准布局结构

瞧,在types特征列表中有is_classis_standard_layout 。 当一个types满足时,它就是一个“结构”。 或者更准确地说,它是一个标准布局结构 ,由C ++ 11§9/ 8定义。


关于

我想知道为什么types特征中没有[class和struct]之间的区别

那么,有。 这是is_standard_layout特性。


关于

检查这种差异总是没有用,还是有更多理由我不明白?

不,检查这种差异并不是无用的。 该标准定义了标准布局 ,因为它非常实用。 正如标准本身所指出的,

C ++ 11§9/ 9 ([class] / 9)

[注意:标准布局类对于用其他编程语言编写的代码进行通信非常有用。 它们的布局在9.2中指定。


笔记:
¹虽然标准定义“一个联合是一个类”,但is_class特征对于一个classstruct是正确的,但对于一个union不是这样。 即这个特性比一般的术语更具体。