Виртуальный базовый класс
От: Waylander123  
Дата: 10.03.14 16:03
Оценка:
Доброго времени суток!

Допустим, есть такая иерархия:
struct Base
{
Base(int){}
};
 
struct Der:virtual Base
{
Der(int):Base(0){}
};
 
struct Derived:Der, Base
{
//Derived(int):Base(0),Der(0),Base(1){}
};


Как здесь инициализировать базовые классы в конструкторе Derived? Ведь по сути тут нужно инициализировать 2 класса Base — виртуальный, который в части Der, и прямой базовый, и возникает что-то вроде неоднозначности. Пишет "error: ‘struct Base’ is both a direct base and an indirect virtual base" (Base является как прямым базовым классом, так и косвенным виртуальным базовым классом), но насколько я знаю, по стандарту такое возможно. И действительно, если конструктор Base сделать по умолчанию, ошибок никаких не выдает, т.к. в таком случае явный вызов конструктора Base можно не писать. Но как быть, если конструктор принимает один или несколько параметров?
Re: Виртуальный базовый класс
От: Abyx Россия  
Дата: 10.03.14 16:10
Оценка: -1 :)
Здравствуйте, Waylander123, Вы писали:

W>
W>struct Base
W>{
W>Base(int){}
W>};
 
W>struct Der:virtual Base
W>{
W>Der(int):Base(0){}
W>};
 
W>struct Derived:Der, Base
W>{
W>//Derived(int):Base(0),Der(0),Base(1){}
W>};
W>


нельзя вызвать конструктор базового класса своего базового класса
In Zen We Trust
Re[2]: Виртуальный базовый класс
От: Waylander123  
Дата: 10.03.14 16:31
Оценка: +1
Здравствуйте, Abyx, Вы писали:

A>нельзя вызвать конструктор базового класса своего базового класса


Но за инициализацию всех виртуальных классов отвечает most derived class (самый производный класс в иерархии), насколько я знаю
Re: Виртуальный базовый класс
От: Erop Россия  
Дата: 10.03.14 19:42
Оценка: 3 (1) +1
Здравствуйте, Waylander123, Вы писали:

W>Как здесь инициализировать базовые классы в конструкторе Derived? Ведь по сути тут нужно инициализировать 2 класса Base — виртуальный, который в части Der, и прямой базовый, и возникает что-то вроде неоднозначности. Пишет "error: ‘struct Base’ is both a direct base and an indirect virtual base" (Base является как прямым базовым классом, так и косвенным виртуальным базовым классом), но насколько я знаю, по стандарту такое возможно. И действительно, если конструктор Base сделать по умолчанию, ошибок никаких не выдает, т.к. в таком случае явный вызов конструктора Base можно не писать. Но как быть, если конструктор принимает один или несколько параметров?


Возможно, есть какой-то специальный синтаксис на эту тему, но я такого не помню, а стандарт читать лень, тем более, то из вопроса не совсем понятно какой именно

Я бы для простоты, ввёл бы просто класс-прокладку, скажем такой:
template<typename TBase> class DerPad : public TBase {
protected:
    DerPad() {}
    DerPad( const TBase& t ) : TBase( t ) {}
    template<typename T1>
        DerPad( const T1& t1 ) : 
            TBase( t1 ) {}
    template<typename T1, typename T2>
        DerPad( const T1& t1, const T2& t2 ) : 
            TBase( t1, t2 ) {}
    template<typename T1, typename T2>
        DerPad( const T1& t1, const T2& t2 ) : 
            TBase( t1, t2 ) {}
    // ... пока не надоест
    ~DerPad() {}
};

ну и выводил бы Derived второй раз не из Base, а из DerPad<Base>...

Другой вопрос в том, зачем это всё вообще понадобилось?
Что такое Base на самом деле, что из него надо вывестись и виртуально и нет?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: Виртуальный базовый класс
От: uzhas Ниоткуда  
Дата: 11.03.14 07:07
Оценка: 2 (1)
Здравствуйте, Waylander123, Вы писали:

W>Ведь по сути тут нужно инициализировать 2 класса Base — виртуальный, который в части Der, и прямой базовый, и возникает что-то вроде неоднозначности.


нашел баг репорт на VS2005, который закрыли как Won't fix: http://connect.microsoft.com/VisualStudio/feedback/details/278759/error-c2584-direct-base-x-is-inaccessible-already-a-base-of-y-is-given-where-it-shouldnt-be
не в курсе что там с новыми студиями. вы какой компилятор используете?
Re: Виртуальный базовый класс
От: Chorkov Россия  
Дата: 11.03.14 07:27
Оценка: 3 (1) +1
Здравствуйте, Waylander123, Вы писали:

У тебя точно, наследование Derived от Base невиртуальное?
Тогда введи отдельный тип для виртуальной базы (или наоборот, для невиратуальной).
Заодно будет решена проблема обращения к членам этих двух баз.

struct Base
{
 Base(int){}
};

struct VirtualBase : Base
{
 VirtualBase(int i) : Base(i) {}
};
 
struct Der:virtual VirtualBase
{
 Der(int):VirtualBase(0){}
};
 
struct Derived:Der, Base
{
 Derived(int):VirtualBase(0),Der(0),Base(1){}
};
Re: Виртуальный базовый класс
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 11.03.14 08:13
Оценка: 1 (1) +1
Здравствуйте, Waylander123, Вы писали:

W>Доброго времени суток!


Как-то так. Это же вариант ромбовидного наследования.
Sic luceat lux!
Re: Виртуальный базовый класс
От: Mr.Delphist  
Дата: 11.03.14 16:13
Оценка: 3 (1) +1
Здравствуйте, Waylander123, Вы писали:


W>struct Derived:Der, Base

W>{
W>//Derived(int):Base(0),Der(0),Base(1){}
W>};
W>[/ccode]

Неудивительно, ведь тут Base() упоминается дважды. К какому из экземпляров — прямому наследованию или неявному через Der, относится каждый из? Стандарт гласит:

10.5 The order in which the base class subobjects are allocated in the most derived object (1.8) is unspecified.


Далее просто Ваш пример один-в-один:

12.6.2.4 If a mem-initializer-id is ambiguous because it designates both a direct non-virtual base class and an inherited
virtual base class, the mem-initializer is ill-formed. [ Example:

struct A { A(); };
struct B: public virtual A { };
struct C: public A, public B { C(); };
C::C(): A() { } // ill-formed: which A?

—end example ]


В общем, Вы собрали классические грабли виртуального наследования в трёх уровнях. Быстрый фикс — добавить дефолтный конструктор для виртуальной базы (впрочем, Вы уже упоминали это). Правильный фикс — вдумчивый пересмотр иерархии наследования, нужна ли она в том виде как сейчас.
Re[2]: Виртуальный базовый класс
От: Waylander123  
Дата: 11.03.14 17:09
Оценка:
Здравствуйте, Mr.Delphist, Вы писали:

MD>

MD>10.5 The order in which the base class subobjects are allocated in the most derived object (1.8) is unspecified.


MD>Далее просто Ваш пример один-в-один:


MD>

MD>12.6.2.4 If a mem-initializer-id is ambiguous because it designates both a direct non-virtual base class and an inherited
MD>virtual base class, the mem-initializer is ill-formed. [ Example:

MD>

MD>struct A { A(); };
MD>struct B: public virtual A { };
MD>struct C: public A, public B { C(); };
MD>C::C(): A() { } // ill-formed: which A?

MD>

MD>—end example ]


Да, точно, просмотрел я этот момент в стандарте
Пробовал на ideone и Visual Studio 2008, причем последняя вполне нормально все компилирует , и приоритеты там справа налево (сначала виртуальный класс единицей, а потом прямой нулем)

Всем спасибо!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.