Znalazłem kilka innych pytań, które wydają się sugerować moje pytanie, ale żadna bezpośrednio nie odpowiedziała na to (nawet the one o prawie tej samej nazwie).Dlaczego upcasting wskaźnika podrzędnego do klasy bazowej czasami zmienia wartość wskaźnika?
Mam klasę potomną C++ wywodzącą się od dwóch rodziców. Tworzę obiekt tej klasy, a następnie umieszczam jego odniesienie do każdego z dwóch rodziców. Wartości rzutowania nie są takie same, chociaż jedna pozostaje wartością odniesienia podrzędnego. Oto kod:
class Mom
{
public:
int a = 1;
};
class Dad
{
public:
int b = 2;
};
class Child : public Mom, public Dad
{
public:
int c = 3;
};
int main()
{
Child* c = new Child; // 0x00C5A618
Mom* m = c; // 0x00C5A618
Dad* d = c; // 0x00C5A61C
return 0;
}
Teraz mam zgadywać, że adresy uzyskano poprzez zastosowanie static_cast <> są te rzeczywistych podobiektów. Tak się składa, że Mom
jest pierwszym obiektem podrzędnym, więc w rzeczywistości ma ten sam adres, co Child
. Dad
to drugi podobiekt, więc znajduje się pod innym adresem.
Jak rozumiem, C-styl rzuca, jak to
Mom* m = (Mom*)c;
Dad* d = (Dad*)c;
będzie stosować static_cast <> kiedy byłoby legalne, aby to zrobić. Rzeczywiście, kiedy faktycznie skompilowałem i wykonałem tę wersję, widziałem to samo zachowanie, co poprzednio.
Kontynuując tę migające sagę, używając ukrytych odlewane, jak to
Mom* m = c;
Dad* d = c;
wykazują takie samo zachowanie, jak również, z którego wywnioskować, że ukryte odlewy zastosować również static_cast <> gdy ekwiwalent jawne oddanych byłoby legalne.
rzutowanie w dół z powrotem do Child
robi to samo:
Child* k = static_cast<Child*>(d); // 0x00C5A618
Wartość w k
jest różna od wartości w d
, które zostały ustawione z powrotem do wartości pierwotnie w c
.
Jestem zgadywania, że w tym przypadku nie jest sprawdzenie run-czas, aby zobaczyć, czy rzeczywiście d
punktów do Dad
podobiektu z Child
obiektu.
Do tej pory wszystko ma sens, ale jestem zaskoczony, że nie ma takiego dostosowania adresu (jeśli jest to słuszne to nazwać) dla hierarchii pojedynczo wyprowadzonych. Oznacza to, że jeśli moja hierarchia jest po prostu Mom
->Dad
->Child
, rzucając odniesienie do Child
do wskaźnika do albo Mom
albo nigdy Dad
zmienia wartość:
class Mom
{
public:
int a = 1;
};
class Dad : public Mom
{
public:
int b = 2;
};
class Child : public Dad
{
public:
int c = 3;
};
int main()
{
Child* c = new Child; // 0x00C5A618
Mom* m = c; // 0x00C5A618
Dad* d = c; // 0x00C5A618
Child* k = static_cast<Child*>(d); // 0x00C5A618
return 0;
}
bym tego spodziewać aby zmienić rozmiar pamięci potrzebnej na każdą dodatkową podklasę lub cztery bajty (rozmiar int). Ale nie robią tego. Wszystkie wskaźniki w powyższym przykładzie, c
, m
, d
i k
, mają tę samą wartość.
Więc teraz mam zgadywać, że obiekty zostały rozplanowane w pamięci z obiektem Mom
w najniższym adresu, dodatkową przestrzeni potrzebnej dla obiektu Dad
następnego w kolejności, a dodatkową przestrzeni potrzebnej do Child
nadchodzi ostatni. Ponieważ adres Dad
to-Mom
, adres byłby taki sam jak adres Mom
, prawda?
Podobnie jest również z Child
, więc jego adres będzie również taki sam jak jego własny adres podobiektu Mom
.
Więc ...
myślę, że to działa tak: w pamięci, obiekty następują po sobie tak, że w czysto pojedynczo pochodzącego hierarchii upcasting i rzutowanie w dół zawsze daje ten sam adres, podczas gdy w mnożyć Hierarchia wyprowadzona, niektóre upcasty dają inny adres, ponieważ nie wszystkie podobiekty będą uruchamiane pod tym samym adresem, co obiekt pochodny. Tak:
Possible Memory Layout for a Singly Derived Hierarchy
+-------+-----+-----+---+
| Child : Dad : Mom : a |
| | +-----+---+
| | : b |
| +-----------+---+
| : c |
+-----------------------+
Possible Memory Layout for a Multiply Derived Hierarchy
+-------+-----+---+
| Child : Mom : a |
| +-----+---+
| : Dad : b |
| +-----+---+
| : c |
+-----------------+
Przepraszam, że mam wałęsał się trochę, ale moje pytanie jest takie: czy fakt, że uskok do niektórych klas bazowych obiektu pomnożyć pochodzącego zmienia wartość odniesienia wyniku fakt, że wartość po odlaniu jest adresem obiektu podstawowego w pamięci?
Tak ........... – Soren