Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

[C++] Виртуальное наследование, конструкторы с параметрами

245
29 декабря 2011 года
~ArchimeD~
1.4K / / 24.07.2006
К стыду своему, обнаружил, что не знаю, как правильно разруливать ситуацию ромбовидного наследования, если имеется конструктор с параметрами. Гугл находит только простые примеры с конструктором по умолчанию. Привожу тут свои попытки:

Итак, есть базовый класс
 
Код:
class Tm_BasePackage
{
public:
    Tm_BasePackage(std::uint64_t nLength, std::uint8_t nType, std::uint64_t nParamBitMap);
    ...
};


Допустим, от него наследуются два других:
Код:
class Tm_TxPackage : virtual public Tm_BasePackage
{
public:
    Tm_TxPackage(std::uint64_t nLength, std::uint8_t nType, std::uint64_t nParamBitMap):
                             Tm_BasePackage(nLength, nType, nParamBitMap) { };
    ...
    virtual std::uint64_t Pack(PkgBuffer& Buffer, std::uint64_t nDataPos = 0) throw () = 0;
};

....

class Tm_RxPackage : virtual public Tm_BasePackage
{
public:
    Tm_RxPackage(std::uint64_t nLength, std::uint8_t nType, std::uint64_t nParamBitMap):
                             Tm_BasePackage(nLength, nType, nParamBitMap) { };
    ...
    virtual bool Unpack(const PkgBuffer& Buffer, std::uint64_t nDataPos = 0) throw () = 0;
};


Каким образом унаследовать одновременно Tm_TxPackage и Tm_RxPackage, не определяя конструктора без параметров в базовом классе?

Этот код удалось скомпилировать:
 
Код:
class Tm_KeepAlivePkg: public Tm_TxPackage, public Tm_RxPackage
{
public:
    Tm_KeepAlivePkg (std::uint64_t nLength, std::uint8_t nType, std::uint64_t nParamBitMap):
                Tm_TxPackage(nLength, nType, nParamBitMap), Tm_RxPackage(nLength, nType, nParamBitMap), Tm_BasePackage(nLength, nType, nParamBitMap) { };

    virtual std::uint64_t Pack(PkgBuffer& Buffer, std::uint64_t nDataPos = 0) throw () { };
    virtual bool Unpack(const PkgBuffer& Buffer, std::uint64_t nDataPos = 0) throw () { };
};

Но меня терзают смутные сомнения, действительно ли нужно всем родительским классам в явном виде передавать параметры (без этого не собирается)?

Как вариант, который тоже собирается, и который мне кажется более правильным - не определять конструкторы с параметрами в классах Tm_RxPackage и Tm_TxPackage, а в их производных инициализировать напрямую Tm_BasePackage.

Просветите, пожалуйста, как умные люди делают :)

UPD: нагуглил таки
http://www.devdoc.ru/index.php/content/view/virtual_inheritance.htm
насколько я понимаю, второй вариант (не определять конструкторы с параметрами в классах Tm_RxPackage и Tm_TxPackage) таки действительно правильный
277
29 декабря 2011 года
arrjj
1.7K / / 26.01.2011
Википедия думает так:
Цитата:

C++ по умолчанию не создает ромбовидного наследования: компилятор обрабатывает каждый путь наследования отдельно, в результате чего объект D будет на самом деле содержать два разных подобъекта A, и при использовании членов A потребуется указать путь наследования (B::A или C::A). Чтобы сгенерировать ромбовидную структуру наследования, необходимо воспользоваться виртуальным наследованием класса A на нескольких путях наследования: если оба наследования от A к B и от A к C помечаются спецификатором virtual (например, class B : virtual public A), C++ специальным образом проследит за созданием только одного подобъекта A, и использование членов A будет работать корректно. Если виртуальное и невиртуальное наследования смешиваются, то получается один виртуальный подобъект A и по одному невиртуальному подобъекту A для каждого пути невиртуального наследования к A. При виртуальном вызове метода виртуального базового класса используется так называемое правило доминирования: компилятор запрещает виртуальный вызов метода, который был перегружен на нескольких путях наследования.



Что мы имеем: создается один объект Tm_BasePackage, но т.к. у него нет конструктора по умолчанию компилятор входит в замешательство не зная от какого из классов ( Tm_TxPackage или Tm_RxPackage ) взять параметры для конструктора. И чтобы не вышло гадости просит программиста явно указать параметры.

240
29 декабря 2011 года
aks
2.5K / / 14.07.2006
Лучше такую иерархию вобще не иметь. Это наиболее правильный способ. Но второй вариант правильней да.
245
29 декабря 2011 года
~ArchimeD~
1.4K / / 24.07.2006
Цитата: aks
Лучше такую иерархию вобще не иметь. Это наиболее правильный способ. Но второй вариант правильней да.



Ну у меня собственно сейчас все виртуальные методы определены в Tm_BasePackage. Но разделить их по подклассам показалось правильнее. Ладно, тогда забью. Спасибо.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог