В чём заключается причина не компиляции следующего кода.
(Если убрать virtual — наследование то всё будет компилироваться)
Мне просто интересно почему в случае с virtual компилятору понадобился default — конструктор?
class Base
{
public:
Base( int n ) : m_n(n) {}
private:
int m_n;
};
class Derived : publicvirtual Base
{
public:
Derived( int n ) : Base( n ) {}
};
class SubDerived : public Derived
{
public:
SubDerived( int n, int m ) : Derived( n ) {}
};
Здравствуйте, 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 : publicvirtual 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>
Здравствуйте, 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 : publicvirtual 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>>
и желательно таки первым -- компилятор конечно переордерит, но может и выругаться предупреждением если включены варнинги...
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.
А в чем причина такого выверта, не формальная "так требует стандарт", а "rationale" (кажется, я правильно употребил термин, если нет — извиняйте, в академиях не обучался), то бишь "ребята из Комитета сотворили такую штуку потому-то и потому-то"?
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Здравствуйте, slava_phirsov, Вы писали:
_>А в чем причина такого выверта, не формальная "так требует стандарт", а "rationale" (кажется, я правильно употребил термин, если нет — извиняйте, в академиях не обучался), то бишь "ребята из Комитета сотворили такую штуку потому-то и потому-то"?
Здравствуйте, slava_phirsov, Вы писали:
_>А в чем причина такого выверта, не формальная "так требует стандарт", а "rationale" (кажется, я правильно употребил термин, если нет — извиняйте, в академиях не обучался), то бишь "ребята из Комитета сотворили такую штуку потому-то и потому-то"?
Поскольку виртуальная база общая для всех (в том числе, при ромбовидном наследовании), то за её конструирование должен отвечать кто-то один.
Тут возможны две стратегии
— гонки: базы рекурсивно инициализируются, как в обычном наследовании, и какая ветка добежала до виртуальной базы раньше, та и молодец
— персональная ответственность: виртуальная база инициализируется финальным классом, — естественно, до того, как конструируются её промежуточные наследники
В первом случае нужно как-то помечать, что каждая виртуальная база инициализирована.
1. Завести рядом с виртуальными базами в лэяуте объекта флажки. Это оверхед по памяти.
2. Завести флажки на стеке, в коде, вызывающем конструктор. Передавать их по ссылке.
3. Статически решить, какая ветка ответственна за вызов какой виртуальной базы. Передавать флажки по значению. При внутреннем ветвлении — конъюнкция входных флажков со своими статическими решениями.
Во втором случае флажок ровно один: финальный это класс или нет. И передаётся по значению. И комбинировать не надо лишний раз. ПРОФИТ!
Здравствуйте, nen777w, Вы писали:
N>В чём заключается причина не компиляции следующего кода. N>(Если убрать virtual — наследование то всё будет компилироваться)
Можно жить поближе к нам;
К тоже людям;
Да, у нас могут быть запятые в коде;
Если ( у вас не компилируется хитро выделенный код(особенно сильно в ООП) )
То спросите соседа;
Eсли сосед пуст
То спросите у гугла;
Энд лифт.