Optimasi basis kosong sangat bagus. Namun, ia datang dengan batasan berikut:
Optimalisasi basis kosong dilarang jika salah satu kelas basis kosong juga merupakan tipe atau basis tipe anggota data non-statis pertama, karena dua sub-objek dasar dari tipe yang sama diharuskan memiliki alamat yang berbeda dalam representasi objek dari tipe yang paling diturunkan.
Untuk menjelaskan batasan ini, pertimbangkan kode berikut. The static_assert
akan gagal. Sedangkan, mengubah salah satu Foo
atau Bar
sebaliknya mewarisi dari Base2
akan mencegah kesalahan:
#include <cstddef>
struct Base {};
struct Base2 {};
struct Foo : Base {};
struct Bar : Base {
Foo foo;
};
static_assert(offsetof(Bar,foo)==0,"Error!");
Saya mengerti perilaku ini sepenuhnya. Apa yang saya tidak mengerti adalah mengapa perilaku tertentu ada . Jelas ditambahkan karena suatu alasan, karena ini merupakan tambahan eksplisit, bukan pengawasan. Apa alasan untuk ini?
Khususnya, mengapa dua sub-proyek dasar harus memiliki alamat yang berbeda? Di atas, Bar
adalah tipe dan foo
variabel anggota tipe itu. Saya tidak melihat mengapa kelas dasar Bar
penting untuk kelas dasar dari jenis foo
, atau sebaliknya.
Memang, saya jika ada, saya harapkan itu &foo
sama dengan alamat Bar
instance yang berisi itu — seperti yang diperlukan dalam situasi lain (1) . Lagipula, saya tidak melakukan apa-apa dengan virtual
warisan, kelas dasar kosong, dan kompilasi dengan Base2
menunjukkan bahwa tidak ada yang rusak dalam kasus khusus ini.
Tetapi jelas alasan ini tidak benar, dan ada situasi lain di mana batasan ini diperlukan.
Katakanlah jawaban harus untuk C ++ 11 atau lebih baru (Saat ini saya menggunakan C ++ 17).
(1) Catatan: EBO ditingkatkan di C ++ 11, dan khususnya menjadi wajib untuk StandardLayoutType
s (meskipun Bar
, di atas, bukan a StandardLayoutType
).
Base *a = new Bar(); Base *b = a->foo;
dengana==b
, tetapia
danb
jelas merupakan objek yang berbeda (mungkin dengan metode virtual yang berbeda)