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 можно не писать. Но как быть, если конструктор принимает один или несколько параметров?
Здравствуйте, Waylander123, Вы писали:
W>Как здесь инициализировать базовые классы в конструкторе Derived? Ведь по сути тут нужно инициализировать 2 класса Base — виртуальный, который в части Der, и прямой базовый, и возникает что-то вроде неоднозначности. Пишет "error: ‘struct Base’ is both a direct base and an indirect virtual base" (Base является как прямым базовым классом, так и косвенным виртуальным базовым классом), но насколько я знаю, по стандарту такое возможно. И действительно, если конструктор Base сделать по умолчанию, ошибок никаких не выдает, т.к. в таком случае явный вызов конструктора Base можно не писать. Но как быть, если конструктор принимает один или несколько параметров?
Возможно, есть какой-то специальный синтаксис на эту тему, но я такого не помню, а стандарт читать лень, тем более, то из вопроса не совсем понятно какой именно
Я бы для простоты, ввёл бы просто класс-прокладку, скажем такой:
ну и выводил бы Derived второй раз не из Base, а из DerPad<Base>... Другой вопрос в том, зачем это всё вообще понадобилось?
Что такое Base на самом деле, что из него надо вывестись и виртуально и нет?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Waylander123, Вы писали:
W>Ведь по сути тут нужно инициализировать 2 класса Base — виртуальный, который в части Der, и прямой базовый, и возникает что-то вроде неоднозначности.
У тебя точно, наследование 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){}
};
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 ]
В общем, Вы собрали классические грабли виртуального наследования в трёх уровнях. Быстрый фикс — добавить дефолтный конструктор для виртуальной базы (впрочем, Вы уже упоминали это). Правильный фикс — вдумчивый пересмотр иерархии наследования, нужна ли она в том виде как сейчас.
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, причем последняя вполне нормально все компилирует , и приоритеты там справа налево (сначала виртуальный класс единицей, а потом прямой нулем)