class A {
int i;
};
class B : public A {
int j;
};
В этом примере, который не использует виртуальное наследование, объект типа B
можно расположить так, как если бы B
был определен следующим образом:
class B0 {
int i;
int j;
};
Как только вы введете виртуальное наследование, это не сработает:
class C : public virtual A {
int k;
};
class D : public virtual A {
int l;
};
class E : public C, public D {
int m;
};
Объект типа C
имеет два int
члена: k
из определения C
и i
из определения A
. Точно так же объект типа D
имеет два int
члена, l
и i
. Все идет нормально. Сложная часть связана с классом E
: у него тоже есть один int
член i
, потому что оба экземпляра A
являются виртуальными базами. Таким образом, ни C
, ни D
не могут быть записаны как B0
выше, потому что тогда E
закончится двумя копиями i
.
Решение состоит в том, чтобы добавить уровень косвенности. Объекты типа C
, D
и E
выглядят примерно так (псевдокод, не пытайтесь его компилировать):
class C0 {
int *cip = &i;
int k;
int i;
};
class D0 {
int *dip = &i;
int l;
int i;
};
class E0 {
// C0 subobect:
int *cip = &i;
int k;
// D0 subobject:
int *dip = &i;
int l;
// E data:
int *eip = &i;
int m;
int i;
};
То, что вы видите в размере E
, - это те дополнительные указатели, которые позволяют иметь единственную копию i
независимо от того, как C
и D
объединены в производном классе. (На самом деле каждый из этих указателей был бы указателем на A
, поскольку A
, безусловно, может иметь более одного члена данных, но это слишком сложно представить в этом простом псевдокоде).
person
Pete Becker
schedule
08.12.2012