Boş taban optimizasyonu harika. Ancak, aşağıdaki kısıtlama ile birlikte gelir:
Aynı tabandaki iki temel alt nesnenin nesne temsili içinde farklı adreslere sahip olması gerektiğinden, boş taban sınıflarından birinin de ilk statik olmayan veri üyesinin türü veya tabanı olması durumunda boş taban optimizasyonu yasaktır. türetilmiştir.
Bu kısıtlamayı açıklamak için aşağıdaki kodu göz önünde bulundurun. static_assert
Başarısız olur. Halbuki ikisinden birini değiştirmek ya Foo
da Bar
devralmak yerine Base2
hatayı önlemek için:
#include <cstddef>
struct Base {};
struct Base2 {};
struct Foo : Base {};
struct Bar : Base {
Foo foo;
};
static_assert(offsetof(Bar,foo)==0,"Error!");
Bu davranışı tamamen anlıyorum. Ne yapmak değil anlamaya olduğunu neden bu özel davranış var . Bir nedenden dolayı açık bir şekilde eklenmiştir, çünkü açık bir eklenti, bir gözetim değil. Bunun mantığı nedir?
Özellikle, iki temel alt nesnenin neden farklı adreslere sahip olması gerekir? Yukarıda, Bar
bir türdür ve foo
bu türün bir üye değişkenidir. Temel sınıfın neden temel sınıf Bar
türüyle ilgili olduğunu anlamıyorum foo
veya tam tersi.
Gerçekten de, eğer bir şey varsa, bunun onu içeren örneğin &foo
adresi ile aynı olmasını beklerdim Bar
- diğer durumlarda olması gerektiği gibi (1) . Sonuçta, virtual
kalıtımla süslü bir şey yapmıyorum , temel sınıflar ne olursa olsun boş ve bu derleme Base2
, bu özel durumda hiçbir şeyin kırılmadığını gösteriyor.
Ancak bu mantık bir şekilde yanlıştır ve bu sınırlamanın gerekli olacağı başka durumlar da vardır.
Diyelim ki cevaplar C ++ 11 veya daha yeni bir sürüm için olmalı (şu anda C ++ 17 kullanıyorum).
(1) Not: EBO, C ++ 11'de yükseltildi ve özellikle StandardLayoutType
s için zorunlu hale geldi (ancak Bar
, yukarıda a değil StandardLayoutType
).
Base *a = new Bar(); Base *b = a->foo;
ilea==b
, ancaka
veb
açıkça (belki farklı sanal yöntem geçersiz kılma özelliği olan) farklı nesnelerdir.