Подтвердить что ты не робот

С++: использование базового класса в качестве реализации интерфейса

В С++ можно использовать другой базовый класс для обеспечения реализации интерфейса (т.е. абстрактного базового класса) в производном классе?

class Base
{
    virtual void myfunction() {/*...*/};
}
class Interface
{
    virtual void myfunction() = 0;
}
class Derived
    : public Base, public Interface
{
    // myfunction is implemented by base
}

Вышеприведенное должно компилироваться, но фактически не работает. Есть ли способ достичь этого эффекта?

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

Спасибо.

4b9b3361

Ответ 1

Если Base не является производным от Interface, вам придется переадресовывать вызовы в Derived. Это только "накладные расходы" в том смысле, что вам приходится писать дополнительный код. Я подозреваю, что оптимизатор сделает его настолько эффективным, как если бы ваша оригинальная идея сработала.

class Interface {
    public:
        virtual void myfunction() = 0;
};

class Base {
    public:
        virtual void myfunction() {/*...*/}
};

class Derived : public Interface, public Base {
    public:
        void myfunction() { Base::myfunction(); }  // forwarding call
};

int main() {
   Derived d;
   d.myfunction();
   return 0;
}

Ответ 2

Попробуйте следующее:

class Interface
{
    virtual void myfunction() = 0;
}
class Base : public Interface
{
    virtual void myfunction() {/*...*/};
}
class Derived
    : public Base
{
    // myfunction is implemented by base
}

Ответ 3

Нет. (не так, так или иначе)

Возможно, вы ошибаетесь, так как все делается на других языках, таких как Java, С#, ActionScript и т.д.

В С++ множественное наследование и управление виртуальными классами делают интерфейсы (используемые на других языках) устаревшими. На этих других языках интерфейсы используются для исправления проблем, возникающих из-за отсутствия множественного наследования (хорошего или плохого, выбор).

Итак, если вы хотите просто предоставить общий интерфейс с помощью некоторых виртуальных методов, предоставляющих стандартные реализации, просто реализуйте в базовом классе:

class Interface
{
    virtual void myfunction() { /*...*/ } ; //default implementation
    virtual void yourFunction()  = 0 ; // this one HAVE TO be implemented by the user
}
class Derived
    : public public Interface // dont' need another clas
{
    // myfunction is implemented by base
    void yourFunction(); // have to implement yourFunction
}
class DerivedB
    : public public Interface // dont' need another clas
{
    void myFunction();// myfunction is implemented by base but we implement it for this specific class
    void yourFunction(); // have to implement yourFunction
}

Если, однако, вы хотите предоставить несколько базовых классов с одинаковыми интерфейсами, тогда подумайте, что ваш класс интерфейса является базой других классов

// in this order
class Interface
{
    virtual void myfunction() = 0;
}
class BaseA : public Interface
{   
    // here "virtual" is optional as if the parent is virtual, the child is virtual too
    virtual void myfunction() {/*...*/}; // BaseA specific implementation
}
class BaseB : public Interface
{
    virtual void myfunction() {/*...*/}; // BaseB specific implementation
}

Однако существует не очень-легкий (read: not recommanded) способ обеспечить реализацию по умолчанию, но заставляя пользователя явно сказать, хочет ли он его использовать или нет. Он использует тот факт, что даже чистые виртуальные функции могут иметь стандартные реализации, которые можно назвать:

class Interface
{
    virtual void myfunction() { /*...*/ } ; //default implementation
    virtual void yourFunction()  = 0 ; // this one HAVE TO be implemented by the user BUT provide a default implementation!
}

// in Interface.cpp 

void Interface::yourFunction() // default implementation of the virtual pure function
{ /*...*/ }

// in Derived.h

class DerivedA
    : public public Interface // dont' need another clas
{
    // myfunction is implemented by base
    void yourFunction(); // have to implement yourFunction -- DerivedA specific
}

class DerivedB
    : public public Interface // dont' need another clas
{
    void myFunction();// myfunction is implemented by base but we implement it for this specific class
    void yourFunction() { Interface::yourFunction(); } // uses default implementation of yourFunction, hidden but existing
}

Но не делайте этого.

Ответ 4

В ответе предполагается, что производный класс хочет быть классом CONCRETE или не абстрактным классом, т.е. желательно иметь возможность создавать объекты типа 'Derived'.. Кроме того, я принимаю публичные функции-члены в своем ответе.

Нет. Производный класс должен реализовать все чистые виртуальные функции, которые он наследует от всех базовых классов. В этом случае 'Base::myfunction', но унаследованный 'Derived' не рассматривается как реализация 'Derived::myfunction'

'Derived::myfunction' все еще должен обеспечить реализацию 'Interface::myfunction'.

Возможна одна возможность: 'Derived::myfunction' может внутренне делегировать 'Base::myfunction'

Однако, если не требуется, чтобы Derived был конкретным классом (который, я сомневаюсь, является целью OP), то указанное расположение классов отлично (с точки зрения языка)

Ответ 5

База и интерфейс - совершенно разные типы. Как компилятор должен знать, что "myfunction" связан? Вы должны реализовать его в Derived, даже если эта реализация просто вызывает базовую версию.