виртуальное наследование
От: nen777w  
Дата: 31.03.10 14:00
Оценка:
В чём заключается причина не компиляции следующего кода.
(Если убрать virtual — наследование то всё будет компилироваться)
Мне просто интересно почему в случае с virtual компилятору понадобился default — конструктор?

class Base
{
public:
    Base( int n ) : m_n(n) {}
private:
    int m_n;
};

class Derived : public virtual Base
{
public:
    Derived( int n ) : Base( n ) {}
};

class SubDerived : public Derived
{
public:
    SubDerived( int n, int m ) : Derived( n ) {}
};
Re: виртуальное наследование
От: Alxndr Германия http://www.google.com/profiles/alexander.poluektov#buzz
Дата: 31.03.10 14:04
Оценка: 8 (1) +1
Здравствуйте, nen777w, Вы писали:

N>В чём заключается причина не компиляции следующего кода.

N>(Если убрать virtual — наследование то всё будет компилироваться)
N>Мне просто интересно почему в случае с virtual компилятору понадобился default — конструктор?

Конструктор базового виртуального класса должен вызываться из конструктора полного объекта (most derived класса)

N>
N>class Base
N>{
N>public:
N>    Base( int n ) : m_n(n) {}
N>private:
N>    int m_n;
N>};

N>class Derived : public virtual Base
N>{
N>public:
N>    Derived( int n ) : Base( n ) {}
N>};

N>class SubDerived : public Derived
N>{
N>public:
N>    SubDerived( int n, int m ) : Derived( n ), Base( n ) {}
N>};
N>
Re[2]: виртуальное наследование
От: zaufi Земля  
Дата: 31.03.10 23:59
Оценка: 1 (1)
Здравствуйте, Alxndr, Вы писали:

A>Конструктор базового виртуального класса должен вызываться из конструктора полного объекта (most derived класса)


N>>
N>>class Base
N>>{
N>>public:
N>>    Base( int n ) : m_n(n) {}
N>>private:
N>>    int m_n;
N>>};

N>>class Derived : public virtual Base
N>>{
N>>public:
N>>    Derived( int n ) : Base( n ) {}
N>>};

N>>class SubDerived : public Derived
N>>{
N>>public:
N>>    SubDerived( int n, int m ) : Base( n ), Derived( n ) {}
N>>};
N>>


и желательно таки первым -- компилятор конечно переордерит, но может и выругаться предупреждением если включены варнинги...
Re[3]: виртуальное наследование
От: Micht  
Дата: 01.04.10 07:57
Оценка:
Здравствуйте, zaufi, Вы писали:

А если так?

...
class SubDerived : public Derived
{
public:
    SubDerived( int n, int m ) : Base( n ), Derived(  m  ) {}
};


Чем проинициализируется Base в итоге? n или m? И как это будет происходить?
Если можно, ссылки на стандарт, где это объясняется.
Re[4]: виртуальное наследование
От: placement_new  
Дата: 01.04.10 08:00
Оценка:
M>Чем проинициализируется Base в итоге? n или m? И как это будет происходить?
M>Если можно, ссылки на стандарт, где это объясняется.

Не вызовет Derived Base.
Re[4]: виртуальное наследование
От: Bell Россия  
Дата: 01.04.10 08:15
Оценка:
Здравствуйте, Micht, Вы писали:

M>А если так?


M>
M>...
M>class SubDerived : public Derived
M>{
M>public:
M>    SubDerived( int n, int m ) : Base( n ), Derived(  m  ) {}
M>};
M>


M>Чем проинициализируется Base в итоге? n или m? И как это будет происходить?

Конструктор Base будет вызван с параметром n.

M>Если можно, ссылки на стандарт, где это объясняется.

12.6.2/5
Initialization shall proceed in the following order:
— First, and only for the constructor of the most derived class as described below, virtual base classes shall
be initialized ...


12.6.2/6
All sub-objects representing virtual base classes are initialized by the constructor of the most derived class
(1.8). If the constructor of the most derived class does not specify a mem-initializer for a virtual base class
V, then V’s default constructor is called to initialize the virtual base class subobject. If V does not have an
accessible default constructor, the initialization is ill-formed. A mem-initializer naming a virtual base class
shall be ignored during execution of the constructor of any class that is not the most derived class.

Любите книгу — источник знаний (с) М.Горький
Re[2]: А теперь - объяснение?
От: slava_phirsov Россия  
Дата: 01.04.10 12:52
Оценка:
Здравствуйте, Alxndr, Вы писали:

...

А в чем причина такого выверта, не формальная "так требует стандарт", а "rationale" (кажется, я правильно употребил термин, если нет — извиняйте, в академиях не обучался), то бишь "ребята из Комитета сотворили такую штуку потому-то и потому-то"?
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[3]: А теперь - объяснение?
От: Alxndr Германия http://www.google.com/profiles/alexander.poluektov#buzz
Дата: 01.04.10 13:17
Оценка:
Здравствуйте, slava_phirsov, Вы писали:

_>А в чем причина такого выверта, не формальная "так требует стандарт", а "rationale" (кажется, я правильно употребил термин, если нет — извиняйте, в академиях не обучался), то бишь "ребята из Комитета сотворили такую штуку потому-то и потому-то"?


Неплохое объяснение здесь:
http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.12
Re[3]: А теперь - объяснение?
От: Кодт Россия  
Дата: 01.04.10 14:00
Оценка:
Здравствуйте, slava_phirsov, Вы писали:

_>А в чем причина такого выверта, не формальная "так требует стандарт", а "rationale" (кажется, я правильно употребил термин, если нет — извиняйте, в академиях не обучался), то бишь "ребята из Комитета сотворили такую штуку потому-то и потому-то"?


Поскольку виртуальная база общая для всех (в том числе, при ромбовидном наследовании), то за её конструирование должен отвечать кто-то один.
Тут возможны две стратегии
— гонки: базы рекурсивно инициализируются, как в обычном наследовании, и какая ветка добежала до виртуальной базы раньше, та и молодец
— персональная ответственность: виртуальная база инициализируется финальным классом, — естественно, до того, как конструируются её промежуточные наследники

В первом случае нужно как-то помечать, что каждая виртуальная база инициализирована.
1. Завести рядом с виртуальными базами в лэяуте объекта флажки. Это оверхед по памяти.
2. Завести флажки на стеке, в коде, вызывающем конструктор. Передавать их по ссылке.
3. Статически решить, какая ветка ответственна за вызов какой виртуальной базы. Передавать флажки по значению. При внутреннем ветвлении — конъюнкция входных флажков со своими статическими решениями.
Во втором случае флажок ровно один: финальный это класс или нет. И передаётся по значению. И комбинировать не надо лишний раз. ПРОФИТ!
Перекуём баги на фичи!
Re: виртуальное наследование
От: flonder  
Дата: 02.04.10 01:27
Оценка:
Здравствуйте, nen777w, Вы писали:

N>В чём заключается причина не компиляции следующего кода.

N>(Если убрать virtual — наследование то всё будет компилироваться)

Можно жить поближе к нам;
К тоже людям;
Да, у нас могут быть запятые в коде;

Если ( у вас не компилируется хитро выделенный код(особенно сильно в ООП) )
  То спросите соседа;
  Eсли сосед пуст
    То спросите у гугла;
Энд лифт.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.