あるクラスがstandard-layout classの条件を満たしたときに保証される動作はいくつかあるが、その中でもとくに重要なものに、クラスのオブジェクトへのアドレスは、クラスの最初の非staticデータメンバーのサブオブジェクトへのアドレスに等しい。というものがある。
struct A { int x ; int y ; } ; A a ; A * a_ptr = &a ; int * ptr = reinterpret_cast<int *>( a_ptr ) ;
この場合、ptrはa.xを指す。これは規格で保証されている。ちなみにこの時、++ptrがa.yを指す保証はない。なぜならば、実装はデータメンバーの間にpaddingを入れるかもしれないからだ。ともかく、このクラスのオブジェクトへのアドレスが、クラスの最初の非staticデータメンバーへのサブオブジェクトのアドレスに等しいというのは、重要な保証だ。
ところで、standard-layout classとなるためには、かなり厳しい条件を満たさなければならないわけだが、その中に、「最初の非staticデータメンバーと、基本クラスとで、同じ型を使わない」というものがある。
// standard-layout classではない例 struct A { } ; struct B : A // 基本クラス { A a ; // 最初の非staticデータメンバー int data ; // 二つ目の非staticデータメンバー } ;
なぜかというと、基本クラスのサブオブジェクトと、データメンバーaは、別々のアドレスを割り当てられていなければ、困るからだ。
struct A { } ; struct B : A { A a ; } ; B obj ; A * p1 = &obj ; // 基本クラスのサブオブジェクトへのアドレス A * p2 = &obj.a ; // データメンバーへのアドレス // p1 != p2が保証される
なぜならば、クラスBに、クラスAというサブオブジェクトは、二つあるからだ。p1 != p2を保証するためには、このようなクラスには、standard-layout classになってもらっては困る。
No comments:
Post a Comment