Реализация виртуальных методов в другой родительской ветви, чем они объявлены в - PullRequest
2 голосов
/ 04 августа 2011

У меня есть следующий код:

#include <iostream>

class Grandma
{
public:
    virtual void foo() = 0;
};

class Mom : public Grandma{};

class Dad
{
public:
    void foo() { std::cout << "dad's foo impl"; }
};

class Me : public Mom, public Dad{};

int main()
{
    Me m;
    m.foo();
}

и получение: cannot instantiate abstract class

Я знаю, что означает эта ошибка, я знаю, что не могу создать экземпляр бабушки из-за чисто виртуального.

Но почему я не могу создать экземпляр Me, когда компилятор знает, что я унаследован от мамы и папы, а папа реализовал foo?

Я знаю, что могу исправить это, добавив foo в Me и внутри него, например, вызовите Dad::foo, но я боюсь, что это не решение для моего случая.

Действительно ли необходимо иметь реализацию виртуального метода между его объявлением и созданным объектом (при обходе)"граф иерархии классов")?См. График ASCI

    A
    |
B1  B2
  \ |   
   C1  C2
    | /
    |/
    D
    |
    E

Когда я хочу создать экземпляр E и получить виртуальное объявление в A, единственный способ запустить его - определить его в A, B2, C1, D или E?и точно так же, когда виртуальное объявление в C2 является единственным способом, чтобы определить его в C2, D или E?

Я знаю, что это может быть глупый вопрос, но у меня был долгой день, и я не могу больше думать.

Пожалуйста, не отвечайте только с - "Это невозможно", но попробуйте добавить объяснение, почему нет.

Спасибо!

РЕДАКТИРОВАТЬ -foo () в Dad, конечно, не должен быть приватным

Ответы [ 3 ]

4 голосов
/ 04 августа 2011

Существует никакого отношения между Dad классом и Grandma классом. Dad и Grandma - это два совершенно разных класса. Учитывая, что метод в Dad не рассматривается как реализация чисто виртуального метода в Grandma и должен быть реализован в классе Me.

Когда вы наследуете от Abstract class (класс, содержащий хотя бы одну чистую виртуальную функцию), производный класс должен переопределить и реализовать ALL чисто виртуальные функции-члены базового класса. Если нет, производный класс тоже становится абстрактным, то же самое относится и к классам, производным от производного класса далее по иерархии.

1 голос
/ 04 августа 2011

Вы правы в том, что виртуальная функция переопределяется только реализациями, предоставляемыми классами, наследующими (потенциально через несколько уровней) от класса, в котором виртуальная функция была первоначально объявлена.

Однако, в зависимости от того, чего вы на самом деле пытаетесь достичь, Делегирование класса сестры может быть тем, что вы хотите. По сути, вы можете объявлять виртуальные функции в базе, общей как для бабушки, так и для папы («Персона»?), И бабушка может вызывать эти функции, даже если только папа предоставляет реализацию, когда вы используете объект Me. Даже если бабушка ничего не знает о папе, когда вы используете виртуальное наследование, любые подклассы, которые ваш конечный класс извлекает, могут использоваться для удовлетворения виртуальных функций из виртуального базового класса.

1 голос
/ 04 августа 2011

К сожалению, вы правы, что вам необходимо реализовать виртуальный метод на пути между исходным объявлением и конечным экземпляром объекта. Объекты с множественным наследованием не могут реализовать этот интерфейс.

Так что из вопроса звучит так, будто вы пытаетесь реализовать родительский интерфейс в дочернем классе, наследуя от разработчика. Вместо этого подхода вы рассматривали вопрос о том, чтобы родительский класс делегировал работу шаблону стратегии, а затем выбирал правильную стратегию в своем дочернем классе. Тогда вы все равно можете составлять реализации вместе, и вам не придется беспокоиться о множестве сложностей множественного наследования.

...