当然,答案是“不”,因为写它的人认为它很难,但我想知道为什么 .
考虑到(无模板)类通常在头文件中声明,然后将其包含在几个单独编译的文件中,请考虑这两个文件:
file1.c
#include <cstddef>
struct Foo {
public:
int pub;
private:
int priv;
};
size_t getsize1(Foo const &foo) {
return sizeof(foo);
}
file2.c
#include <cstddef>
struct Foo {
public:
int pub;
private:
int priv;
};
size_t getsize2(Foo const &foo) {
return sizeof(foo);
}
通常,Foo将在头文件中声明并包含在两者中,但效果如上所示 . (也就是说,包含 Headers 不是魔术,它只是将 Headers 内容放在该行上 . )我们可以编译它们并将它们链接到以下内容:
main.cc
#include <iostream>
struct Foo {
public:
int pub;
private:
int priv;
};
size_t getsize1(Foo const &);
size_t getsize2(Foo const &);
int main() {
Foo foo;
std::cout << getsize1(foo) << ", " << getsize2(foo) << ", " << sizeof(foo) << '\n';
}
一种方法是使用g:
g++ -std=c++11 -c -Wall file1.cc
g++ -std=c++11 -c -Wall file2.cc
g++ -std=c++11 -c -Wall main.cc
g++ -std=c++11 -Wall *.o -o main
(在我的架构和环境中),显示:8,8,8 . 对于file1.cc,file2.cc和main.cc的每个编译,sizeof是相同的
但是c 11标准是否能保证这一点,是否真的可以期待与所有3 Foo的布局兼容? Foo包含私有和公共字段,因此它不是c 11标准(工作草案)第9条第7项中定义的标准布局结构:
标准布局类是一个类:没有非标准布局类(或此类类型的数组)或引用的非静态数据成员,没有虚函数(10.3)且没有虚基类(10.1) ),对所有非静态数据成员具有相同的访问控制(第11条),没有非标准布局基类,在最派生类中没有非静态数据成员,并且最多只有一个非基类-static数据成员,或者没有具有非静态数据成员的基类,并且没有与第一个非静态数据成员相同类型的基类 .
由于我们正在使用结构,并且要彻底,下一个标准说:
标准布局结构是使用类键结构或类键类定义的标准布局类 . 标准布局联合是使用类 - 键联合定义的标准布局类 .
据我所知,标准只定义了标准布局中结构之间的布局兼容性(第9.2条,第18条) .
如果两个标准布局结构(第9节)类型具有相同数量的非静态数据成员,并且相应的非静态数据成员(按声明顺序)具有布局兼容类型(3.9),则它们是布局兼容的 .
因此,保证所有三个Foo都是布局兼容的,更重要的是为什么?
为什么在编译期间为Foo创建不同布局的(非确定性)编译器不是c 11编译器?
1 回答
这三个
Foo
是布局兼容的,因为它们是相同的类型,struct ::Foo
.这些类是相同的类型,因为它们具有相同的(完全限定的)名称并具有外部链接:
在命名空间范围内声明的未在未命名的命名空间中声明(递归)的类名称具有外部链接:
请注意,只要定义包含相同的标记序列,就允许在不同的翻译单元中出现多个类类型的定义:
因此,如果
Foo
具有不同的名称,则它们的类型不同;如果它们出现在匿名命名空间内或函数定义中(内联函数除外;请参阅 [dcl.fct.spec] / 4),它们将不具有外部链接,因此不会是相同的类型 . 在任何一种情况下,只有当它们是标准布局时,它们才是布局兼容的 .一些例子:
两个
Foo
是相同的类型 .ODR违规;未定义的行为 .
不同的名字,所以不同的类型 . 不兼容布局 .
不同的名称,不同的类型,但布局兼容(自标准布局) .
内部联系;不同种类 .
没有联系;不同种类 .
[dcl.fct.spec] / 4的相同类型 .