Множественное наследование с абстрактными и определенными наследуемыми функциями с тем же именем - PullRequest
4 голосов
/ 12 февраля 2012

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

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

Пример:

class A
{
    public:
    virtual void Set(int X) = 0;
};

class B
{
    public:
    virtual void Set(int X);
};

class AB : public A, public B
{
    //other methods not relevant to example go here
};

int main(int argc, char **argv)
{
    int Y = 5;
    A* ObjectA = new AB();
    ObjectA->Set(Y);
    return 0;
}

До сих пор мои попытки скомпилировать этот базовый пример были встречены с ошибками, которые говорят:

'AB': невозможно создать экземпляр абстрактного класса из-за следующих членов: 'void A :: Set(int) ': is abstract

Когда я проводил собственное исследование, я не мог найти четкого ответа, но, основываясь на других вопросах, связанных со смежными темами, я обнаружил, что используя «using B ::»Набор "в классе AB может помочь с этим.Но когда я пытаюсь добавить его в определение класса AB, ошибка не устраняется.

Можно ли как-нибудь это сделать?

Ответы [ 3 ]

2 голосов
/ 12 февраля 2012

Если бы у вас было 2 нормальные функции Set в A и B, то using B::Set сообщит компилятору, что если у вас есть объект класса AB и вызовите метод Set этого объекта, B::Set будет вызвано, если AB::Set явно не определено.

Ваша ситуация другая.У вас есть чисто виртуальная функция A::Set, которая приводит A к абстрактному классу.Поскольку AB не переопределяет A::Set, AB тоже становится абстрактным, поэтому вы не можете создать его экземпляр.

Что вы можете сделать здесь

Вы можете реализовать AB::set дляcall B::Set:

class AB : public A, public B
{
public:
    void Set(int x) { return B::Set(x); }
};

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

0 голосов
/ 24 ноября 2014

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

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

0 голосов
/ 12 февраля 2012

Вы пытались реализовать метод:

class AB : public A, public B
{
    void Set(int X) {}
};

Причина, по которой он не работает, в том, что A::Set() чисто виртуальный. То есть у него нет реализации. Но вы пытаетесь назвать это. Вы должны переопределить его в производном классе, чтобы иметь возможность создавать экземпляр производного класса.

using не работает в вашем случае, потому что у вас есть A*, так что нет никакой двусмысленности для компилятора.

В случае, если у вас было:

AB* ObjectA = new AB();
ObjectA->Set(Y);

вам придется использовать using в объявлении AB для устранения неоднозначности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...