我已经看到,为了检查类型T
是否是我可以使用的类:
bool isClass = std::is_class<T>::value;
对于类和结构都返回true。我知道在C ++中它们几乎是一样的,但我想知道为什么在类型特征中它们之间没有区别。检查这种差异总是没用的,还是有一些我不理解的理由?
答案 0 :(得分:165)
对于类和结构都返回true。我知道在C ++中它们几乎是一样的,但我想知道为什么在类型特征中它们之间没有区别。
不幸的是,这是C ++中常见的误解。有时它来自于基本的误解,但有时它来自于英语的含糊不清。它可能来自不准确的编译器诊断,写得不好的书籍,不正确的SO答案......
你可能读过这样的东西:
“除了成员和基础的默认可见性之外,结构和类之间的C ++没有区别。”
这段经文可以被误解,因为当使用“无差异”这样的短语时,身份和平等的概念很难区分。< / p>
事实上,自1985年以来,C ++一直没有结构。它只有类。
The kind of types that you declare with the keyword class
and the keyword struct
are classes。期。关键字struct
以及使用该关键字定义类时默认的可见性规则仅用于向后兼容C ...但这是语法问题。它不会使结果类型实际上属于不同类型。
类型特征没有区别,因为实际上不是一个可以制作的。
答案 1 :(得分:26)
无法区分像
这样的空定义的语义差异class C {
public:
};
这
struct S {
};
或类似地
class C {
};
和
struct S {
private:
};
除struct
vs class
关键字外,没有可检测到的行为差异。另请参阅this Q&A。
注意:正如@KyleStrand所述,派生还需要显式访问说明符,因此S : private Base {};
和C : Base {};
是等价的,与S : Base {};
和{相同{1}},其中C : public Base {};
是结构,S
是一个类,C
可以是。
答案 2 :(得分:23)
他们是同一件事。唯一的区别(默认成员可见性)仅在编译时存在。在struct
和class
之间没有任何区别。
ETA:您可能想要的是std::is_pod
,它会告诉您您的班级是否是一个普通的旧数据类型&#34;。关于这个问题的大部分讨论和评论似乎都表明,这就是那些认为应该有区别的人。
答案 3 :(得分:14)
其他人已经正确地指出,在C ++中,关键字struct
和class
具有相同的含义,除了成员可见性的差异。
您是否调用聚合类型,因此定义“结构”或“类”或“weiruewzewiruz”取决于您。为了沟通,通常建议遵循既定的惯例,因此我建议反对“weiruewzewiruz”。
还建议使用语义差异作为单词选择的指导。对于没有大量内部逻辑和不变量的简单聚合数据,struct
的使用更为常见;典型的用途是struct point { float x; float y; };
。这些类型在文献中通常称为“结构”或“结构”。如果在C ++中使用fprintf
的人将第一个参数称为“指向FILE结构的指针”,那就不足为奇了。 FILE是Scott Meyers在“更有效的C ++”中的意思,第34项:
可以安全地假设编译在两者中的结构定义 语言[C和C ++ -p.a.s]由两个编译器以相同的方式布局。
关于自然语言,单词选择“结构”并非巧合:Meyers正在谈论一种普通的旧数据集合,它在两种语言中具有相同的语义,直到位级别。
关于编程语言,如果所讨论的数据聚合的C ++定义使用关键字struct
或class
(使用公共访问说明符),则无关紧要。 struct
可能是更自然的选择,因为聚合的C ++语义是C结构的语义。此外,使用struct
可以使C和C ++源更容易共享一个类型定义。
C ++标准在自然语言和编程语言中都使用“struct”和“structure”,不仅在互操作性的情况下:1.7 / 5:“声明为”的结构,或3.2 / 4 struct X; // declare X as a struct type
。最有趣的是9/8,为互操作标准奠定了基础:
8标准布局结构是标准布局类 使用class-key结构或类键定义 类。 [...]
任何阅读此内容的人都可以声称C ++中没有任何结构是超出我的。这显然不是编辑错误,因为术语“struct”和“class”是相互明确设置的。
然而,比单词选择和品味问题更有趣的是明显的,可测试的差异。在什么情况下C ++聚合与Cstruct
相当并且兼容?也许这个问题是你的问题的根源?报价中提到的标准布局是标准。它在9/7中有详细说明,基本上规定了
标准然后说
9 [注意:标准布局类对于通信很有用 使用其他编程语言编写的代码。 它们的布局在9.2.-尾注]中指定。
当然,在C中编译的结构定义符合这些标准,因此Scott Meyers的主张。来自stdio.h的FILE
是一个突出的,不是非常重要的例子。请注意,标准不提供保证,因为对象布局是依赖于实现的,并且可能仅使用编译器选项进行更改。
是否可以使用特征类型std::is_standard_layout<T>
测试类是否具有标准布局。以下程序受an example on 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
答案 4 :(得分:7)
C ++11§9/ 10 ([class] / 10) :“ 标准布局结构是使用 class-key
struct
或<定义的标准布局类em> class-keyclass
。 标准布局联合是使用 class-keyunion
定义的标准布局类。
“ POD结构是一个非联合类,它既是一个普通类,也是一个标准布局类,没有 非POD结构类型的非静态数据成员,非POD联合(或此类型的数组)。 [...]
由于 POD结构是标准布局类,因此它是标准布局结构的子集。据我所知,这是C ++标准中 struct 的最一般含义。所以你想要的是一个类型特征或一组类型特征,它们可以让你识别标准布局结构。
瞧,查看类型特征列表is_class
和is_standard_layout
。当一种类型令人满意时,它就是一个“结构”。或者更准确地说,它是标准布局结构,由C ++11§9/ 8定义。
关于
“我想知道为什么类型特征中的[class和struct]之间没有区别
嗯,有。这是is_standard_layout
特征。
关于
“检查这种差异总是没用,还是有更多我不理解的理由?
不,检查这种差异并非毫无用处。该标准定义了标准布局,因为它非常实用。正如标准本身所说,
C ++11§9/ 9 ([class] / 9) :“ [注意:标准布局类对于与使用其他编程语言编写的代码进行通信非常有用。它们的布局在9.2.-尾注]中指定。
注意:
¹is_class
或class
的{{1}}特征是真的,但struct
的特征是真的,即使标准定义“联合是一个类”。即特征比一般术语更具体。
功能