Garantias no endereço do Baseclass em C ++?
-
24-09-2019 - |
Pergunta
Em C Struct, tenho certeza que:
struct Foo { ... };
struct Bar {
Foo foo;
...
}
Bar bar;
assert(&bar == &(bar.foo));
Agora, em C ++, se eu tiver:
class Foo { ... };
class Bar: public Foo, public Other crap ... {
...
}
Bar bar;
assert(&bar == (Foo*) (&bar)); // is this guaranteed?
Se sim, você pode me dar uma referência (como "a linguagem de programação C ++, página xyz")?
Obrigado!
Solução
Não há garantia. Do padrão C ++ 03 (10/3, classe.Derived):
A ordem em que os subobjetos da classe base são alocados no objeto mais derivado (1.8) não é especificado.
Outras dicas
Mesmo que o layout das classes base seja não garantido Na maneira como você parece estar pensando (e mesmo que haja mais garantias para os membros), isso é garantido:
Bar bar;
assert(&bar == (Foo*) (&bar));
Porque o elenco usa um static_cast (por 5.4) que será convertido &bar
Corretamente, e a comparação entre ponteiro para base e ponteiro para derivado será convertido da mesma forma.
Isso, no entanto, não seria garantido:
Bar bar;
void* p1 = &bar;
void* p2 = (Foo*)&bar;
assert(p1 == p2); // not guaranteed
Não imagino que seja, não sei por que precisaria ser.
Eu tenho uma questão relacionada.
Se você tem herança de diamante:
class Base(){ virtual void AFunc(){} };
class A:Base{};
class B:Base{void AFunc(){} }
class Test:A,B{};
Base * b = (Base*)new Test;
b->AFunc();
Vamos supor que a estrutura da memória seja base: a: b: teste,
Nota No ponto de chamada, tudo o que o compilador sabe é o endereço do início do objeto, e o AFUNC espera ser relativo ao início do objeto B, esses dois endereços não serão os mesmos! Então, como isso funciona?
Como se B fosse do tipo B, os dois endereços seriam os mesmos ...