もちろん、答えは「いいえ」です。なぜなら、それを書いた人々はそれについて真剣に考えたからです。しかし、私はその理由を知りたいです。
(テンプレートのない) クラスはヘッダー ファイルで宣言されることが多く、それらは個別にコンパイルされるいくつかのファイルに含まれていることを考慮して、これら 2 つのファイルを再検討してください。
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 はヘッダー ファイルで宣言され、両方に含まれますが、効果は上記のとおりです。(つまり、ヘッダーを含めることは魔法ではありません。ヘッダーのコンテンツをその行に配置するだけです。)両方をコンパイルして、次のようにリンクできます。
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';
}
これを行う 1 つの方法は、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。sizeofは、file1.cc、file2.cc、およびmain.ccの各コンパイルで同じです
しかし、c++11 標準はこれを保証していますか? 3 つすべての Foo とレイアウトの互換性があると期待しても本当に問題ないのでしょうか? Foo にはプライベート フィールドとパブリック フィールドの両方が含まれているため、c++11 標準 (ワーキング ドラフト) の第 9 節の 7 で定義されている標準レイアウトの構造体ではありません。
標準レイアウト クラスは、次のようなクラスです。
- タイプ非標準レイアウト クラス (またはそのようなタイプの配列) または参照の非静的データ メンバーを持たない、
- 仮想関数 (10.3) も仮想基本クラス (10.1) もありません。
- すべての非静的データメンバーに対して同じアクセス制御 (条項 11) を持ち、
- 非標準レイアウトの基本クラスはありません。
- 最も派生したクラスに非静的データ メンバーがなく、非静的データ メンバーを持つ基本クラスが最大 1 つあるか、または非静的データ メンバーを持つ基本クラスがない。
- 最初の非静的データ メンバーと同じ型の基底クラスはありません。
構造体を使用しているため、徹底的にするために、次のパーは次のように述べています。
標準レイアウト構造体は、class-key 構造体または class-key クラスで定義された標準レイアウト クラスです。標準レイアウト ユニオンは、クラス キー ユニオンで定義された標準レイアウト クラスです。
私の知る限りでは、標準は標準レイアウトの構造体間のレイアウト互換性のみを定義しています (条項 9.2、par 18)。
2 つの標準レイアウト構造体 (条項 9) 型は、同じ数の非静的データ メンバーを持ち、対応する非静的データ メンバー (宣言順) がレイアウト互換型 (3.9) を持っている場合、レイアウト互換性があります。
では、3 つの Foo がすべてレイアウト互換であることが保証されているのでしょうか? さらに重要なことに、その理由は?
コンパイル中に Foo のさまざまなレイアウトを作成する (非決定論的) コンパイラが c++11 コンパイラではないのはなぜですか?