Я пытался решить ту же самую проблему; Я выдвинул несколько идей, таких как использование шаблонов с переменными числами и расширение пакета, чтобы учесть произвольное количество родителей, но я понял, что это приведет к реализации, такой как 'super0' и 'super1'. Я уничтожил его, потому что это было бы чуть более полезным, чем отсутствие его для начала.
Мое решение включает вспомогательный класс PrimaryParent
и реализовано так:
template<typename BaseClass>
class PrimaryParent : virtual public BaseClass
{
protected:
using super = BaseClass;
public:
template<typename ...ArgTypes>
PrimaryParent<BaseClass>(ArgTypes... args) : BaseClass(args...){}
}
Тогда какой класс вы хотите использовать, будет объявлен так:
class MyObject : public PrimaryParent<SomeBaseClass>
{
public:
MyObject() : PrimaryParent<SomeBaseClass>(SomeParams) {}
}
Чтобы избежать необходимости использовать виртуальное наследование в PrimaryParent
для BaseClass
, конструктор, принимающий переменное число аргументов, используется для построения BaseClass
.
Причина наследования public
BaseClass
в PrimaryParent
заключается в том, что MyObject
имеет полный контроль над наследованием BaseClass
, несмотря на наличие класса помощника между ними.
Это означает, что каждый класс, который вы хотите иметь super
, должен использовать вспомогательный класс PrimaryParent
, и каждый дочерний элемент может наследовать только один класс, используя PrimaryParent
(отсюда и название).
Другое ограничение для этого метода: MyObject
может наследовать только один класс, который наследуется от PrimaryParent
, и этот должен быть унаследован с использованием PrimaryParent
. Вот что я имею в виду:
class SomeOtherBase : public PrimaryParent<Ancestor>{}
class MixinClass {}
//Good
class BaseClass : public PrimaryParent<SomeOtherBase>, public MixinClass
{}
//Not Good (now 'super' is ambiguous)
class MyObject : public PrimaryParent<BaseClass>, public SomeOtherBase{}
//Also Not Good ('super' is again ambiguous)
class MyObject : public PrimaryParent<BaseClass>, public PrimaryParent<SomeOtherBase>{}
Прежде чем вы откажетесь от этого в качестве опции из-за кажущегося количества ограничений и того факта, что между каждым наследованием существует класс среднего уровня, эти вещи не плохие.
Множественное наследование является сильным инструментом, но в большинстве случаев будет только один первичный родитель, и, если есть другие родители, они, вероятно, будут классами Mixin или классами, которые в любом случае не наследуются от PrimaryParent
. Если множественное наследование все еще необходимо (хотя во многих ситуациях было бы полезно использовать композицию для определения объекта вместо наследования), чем просто явно определить super
в этом классе и не наследовать от PrimaryParent
.
Идея определения super
в каждом классе не очень привлекательна для меня, использование PrimaryParent
позволяет super
, явно основанному на наследовании псевдониму, оставаться в строке определения класса вместо тела класса. куда должны идти данные.
Хотя это может быть только я.
Конечно, каждая ситуация отличается, но учтите, что я сказал, когда решал, какой вариант использовать.