Как я могу переопределить чисто виртуальный метод, используя частно унаследованный метод?

У меня есть следующее:

class Abstract
{
    virtual void AbstractMethod() = 0;
};

class Implementer
{
    void AbstractMethod() {};
};

class Concrete : public Abstract, private Implementer
{};

Я не могу создать экземпляр Concrete, потому что чисто виртуальный метод AbstractMethod не переопределен. Что я делаю не так?


person Dan Nestor    schedule 30.06.2014    source источник
comment
Почему вы не наследуете от Abstract в Implementer?   -  person Cogwheel    schedule 01.07.2014
comment
@Cogwheel - мне кажется, он более четко выражает концепции, которые я пытаюсь использовать   -  person Dan Nestor    schedule 01.07.2014
comment
На самом деле я думаю, что это действительно дубликат этого: stackoverflow.com/q/23153328/103167   -  person Ben Voigt    schedule 01.07.2014


Ответы (1)


Вы используете множественное наследование здесь.

Бетон имеет две иерархии, рассматриваемые отдельно:

Аннотация и исполнитель. Поскольку Abstract не имеет отношения к Implementer, ваше использование виртуального в этом случае (для наследования братьев и сестер) не удастся.

Вам нужно переопределить виртуальные функции в производных классах. Вы не можете сделать это так, как пытаетесь.

В частности, если бы вы переписали его как таковой, это сработало бы:

class Abstract
{
    virtual void AbstractMethod() = 0;
};

class Implementer : private Abstract
{
    void AbstractMethod() {};
};

class Concrete : public Implementer
{};

Я хотел бы отметить, что использование вами открытого или закрытого наследования в Concrete не влияет на проблему. Если вы измените Implementer на public в исходном примере, он все равно не будет конкретным классом.

Полезная вспомогательная информация. По возможности избегайте множественного наследования, отдавайте предпочтение композиции, а не наследованию, и поверхностному наследованию, а не глубокому. http://en.wikipedia.org/wiki/Composition_over_inheritance

Если вы идете по пути множественного наследования, имейте в виду, что в С++ по умолчанию используются отдельные иерархии наследования, а также необходимость виртуального наследования для объединения различных путей (виртуальные методы по-прежнему требуют, чтобы производный класс переопределял их, а не родственные классы): http://en.wikipedia.org/wiki/Multiple_inheritance

person M2tM    schedule 30.06.2014
comment
То есть две иерархии никак не могут быть объединены в Concrete? - person Dan Nestor; 01.07.2014
comment
@Deduplicator - я тоже не смог написать программу, что бы тоже избавиться от ошибки ;) - person Dan Nestor; 01.07.2014
comment
@DanNestor, вы можете использовать виртуальное наследование, чтобы избежать нескольких иерархий, которые имеют общий базовый класс, но нет, не так, как вы хотите для переопределения виртуальных методов. - person M2tM; 01.07.2014
comment
@DanNestor также лучше ограничить использование множественного наследования, где это возможно. Множественное наследование абстрактных базовых классов относительно безвредно (и может быть полезно для указания интерфейсов, подобных Java/C#, насколько мне известно), но может стать довольно сложным, когда у вас есть общее состояние. Это всего лишь предостережение. По возможности отдавайте предпочтение композиции и поверхностному наследованию, а не глубокому и ветвящемуся полиморфизму. Полезно прочитать: en.wikipedia.org/wiki/Composition_over_inheritance - person M2tM; 01.07.2014