Здравствуйте Sashko, Вы писали:
S>Может не поверишь, Игорь, но иногда небольшой смысл есть ;). С virtual наследованием (хотя эта вещь закладывалась как раз для полиморфного наследования) можно делать вот такую вещь
S>При виртуальном наследовании, в конструкторе наследника (любого уровня) мы должны указывать как инициализируется базовый виртуальный класс. Если в списке инициализации конструктора наследника, явно не указан конструктор базового виртуального класса, то будет использоваться конструктор по умолчанию (если такового нет, то компилятор выдаст ошибку). Таким образом, в наследнике любого уровня, легко можно проинициализировать базовый класс (в TurboVision было похожее использование виртуального наследования). Не спорю, что, то же самое можно сделать и без виртуального наследования, удобно это или нет, решать самому.
На этом принципе основан также родственный трюк, позволяющий обозначать определенные классы как финальные, т.е. как классы, от которых нельзя наследовать:
class VB
{
friend class CFinal;
private:
VB() {}
};
// Пример финального класса
class CFinal : private virtual VB
{
};
В данном примере от класса 'CFinal' нельзя унаследовать никакие другие классы. Если попытаться это сделать, то на класс-наследник будет возложена обязанность констуирования виртуальной базы 'VB'. А он этого сделать не может, т.к. не имеет доступа к конструктору класса 'VB'.
Этот прием можно оформить более универсально через шаблоны:
template <class T_>
class CInheritanceStopper
{
friend class T_;
private:
CInheritanceStopper() {}
};
////////////////////////////////////
// Пример финального класса
class CFinal : private virtual CInheritanceStopper<CFinal>
{
};
Или еще более элегантный вариант:
template <class T_> class CInheritanceStopper;
template <class T_>
class CInheritanceStopper_
{
friend class T_;
friend class CInheritanceStopper<T_>;
private:
CInheritanceStopper_() {}
};
template <class T_>
class CInheritanceStopper : private virtual CInheritanceStopper_<T_> {};
////////////////////////////////////
// Пример финального класса
class CFinal : CInheritanceStopper<CFinal>
{
};