Jep*_*sen 56 c++ type-traits c++11
我已经看到,为了检查类型T是否是我可以使用的类:
bool isClass = std::is_class<T>::value;
Run Code Online (Sandbox Code Playgroud)
它对类和结构都返回true.我知道在C++中它们几乎是一样的,但我想知道为什么在类型特征中它们之间没有区别.检查这种差异总是没用,还是有一些我不理解的理由?
Lig*_*ica 167
它对类和结构都返回true.我知道在C++中它们几乎是一样的,但我想知道为什么在类型特征中它们之间没有区别.
不幸的是,这是C++中常见的误解.有时它来自于基本的误解,但有时它来自于英语的含糊不清.它可能来自不准确的编译器诊断,写得不好的书,不正确的SO答案......
你可能读过这样的东西:
"除了成员和基础的默认可见性之外,结构和类之间的C++没有区别."
这段经文可以被误解,因为在使用诸如"无差异"之类的短语时,很难区分身份和平等的概念.
事实上,自1985年以来,C++还没有结构.它只有类.
您使用关键字class和关键字声明的类型struct是类.期.关键字struct和使用该关键字定义类时默认的可见性规则只是为了与C ...向后兼容而保留,但这是一种语法.它不会使得到的类型实际上是另一种类型.
类型特征没有区别,因为字面意思不是一个要做的.
Tem*_*Rex 27
对于像空的定义,不可能区分语义的差异
class C {
public:
};
Run Code Online (Sandbox Code Playgroud)
从
struct S {
};
Run Code Online (Sandbox Code Playgroud)
或类似的
class C {
};
Run Code Online (Sandbox Code Playgroud)
和
struct S {
private:
};
Run Code Online (Sandbox Code Playgroud)
除structvs class关键字外,没有可检测到的行为差异.另见此问答.
注:由于通过说过@KyleStrand,推导也需要明确的访问说明,所以S : private Base {};和C : Base {};是等价的,同为S : Base {};和C : public Base {};,其中S是一个结构,C是一类,并且Base可以是.
Rob*_*b K 24
他们是一回事.唯一的区别(默认成员可见性)仅在编译时存在.否则在struct和之间没有任何区别class.
ETA:你可能想要的是std::is_pod,它将告诉你你的班级是否是"普通旧数据类型".关于这个问题的大部分讨论和评论似乎表明,这就是那些认为应该有区别的人真正想要的.
Pet*_*ica 15
也有人指出正确的,在C++中的关键字struct,并class具有除了在会员能见度差的含义相同.
您是否调用聚合类型,因此定义"结构"或"类"或"weiruewzewiruz"取决于您.为了沟通,通常建议遵循既定的惯例,因此我建议反对"weiruewzewiruz".
还建议使用语义差异作为单词选择的指导.对于struct没有大量内部逻辑和不变量的简单聚合数据,使用更为常见; 一个典型的用途是struct point { float x; float y; };.这些类型在文献中通常称为"结构"或"结构".如果有人fprintf在C++中使用将第一个参数称为"指向FILE结构的指针" ,那就不足为奇了.FILE是Scott Meyers在"更有效的C++"中的含义的一个例子,第34项:
可以安全地假设两种语言编译的结构定义[C和C++ -pas]由两个编译器以相同的方式排列.
关于自然语言,单词选择"结构"并非巧合:迈耶斯正在谈论一种普通的旧数据集合,它在两种语言中具有相同的语义,直到位级别.
关于编程语言,如果所讨论的数据聚合的C++定义使用了关键字struct或class(使用公共访问说明符),则无关紧要.struct也许是更自然的选择,因为聚合的C++语义是C结构的语义.此外,使用structC和C++源可以更轻松地共享一个类型定义.
C++标准在自然语言和编程语言中使用"struct"和"structure",不仅在互操作性的情况下:1.7/5:"结构声明为",或3.2/4 struct X; // declare X as a struct type.最有趣的是9/8,为互操作标准奠定了基础:
标准布局结构是使用类键结构或类键类定义的标准布局类.[...]
任何阅读此内容的人都可以声称C++中没有任何结构是超出我的.这显然不是编辑错误,因为术语"struct"和"class"是相互明确设置的.
然而,比单词选择和品味问题更有趣的是明显的,可测试的差异.在什么情况下C++聚合与C相当并且兼容struct?也许这个问题是你的问题的根源?报价中提到的标准布局是标准.它在9/7中详细说明,并且基本上规定了这一点
然后标准说
9 [注意:标准布局类对于与使用其他编程语言编写的代码进行通信非常有用.它们的布局在9.2中指定.-尾注]
当然,在C中编译的结构定义符合这些标准,因此Scott Meyers的断言.FILE来自stdio.h是一个突出的,不是非常重要的例子.请注意,标准不保证,因为对象布局是依赖于实现的,并且可能仅使用编译器选项进行更改.
是否具有标准布局的类可以使用类型特征进行测试std::is_standard_layout<T>.以下程序受到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>();
}
Run Code Online (Sandbox Code Playgroud)
示例会话:
$ 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
Run Code Online (Sandbox Code Playgroud)
C++11§9/ 8 ([class]/8):
C++11§9/ 10 ([class]/10):"甲标准布局结构是与定义的标准布局类类键
struct或类键class.甲标准布局联盟是与定义的标准布局类类键union.
"甲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特征对于a class或struct,但不适用于a union,即使标准定义"联合是一个类".即特征比一般术语更具体.