Два интерфейса, множественное наследование объединить в один контейнер?

Я наткнулся на следующую проблему: у меня есть два пакета A и B, работающие нормально для каждого. У каждого свой интерфейс и своя реализация. Теперь я создал пакет C, объединяющий адаптер A с конкретной реализацией B. C фактически только реализует интерфейс A и пока только наследует и использует интерфейс B внутренне. В большинстве случаев этого было достаточно, чтобы иметь доступ только к интерфейсу A из контейнера, но теперь мне нужны также методы из B, доступные. Вот простой пример:

//----Package A----
class IA 
{virtual void foo() = 0;}; 
// I cant add simply bar() here, it would make totally no sense here...

class A : public IA
{virtual void foo() {doBasicWork();} };

//----Package B----
class IB
{virtual void bar() = 0;};

class B1 : public IB
{
    //Some special implementation
    virtual void bar() {} 
};

class B2 : public IB
{
    //Some special implementation
    virtual void bar() {} 
};
// + several additional B classes  , with each a different implementation of bar()

//---- Mixed Classes
class AB1 : public B1, public A
{
void foo() {A::foo(); B1::bar();}
};

class AB2 : public B2, public A
{
void foo() {A::foo(); B2::bar();}
};

// One Container to rule them all: 
std::vector<IA*> aVec;
AB1 obj1;
AB2 obj2;

int main(){
    iAvector.push_back(&obj1);
    iAvector.push_back(&obj2);
    for (std::vector<IA>::iterator it = aVec.begin(); it != aVec.end(); it++)
    {
        it->for(); // That one is okay, works fine so far, but i want also :
//      it->bar(); // This one is not accessible because the interface IA 
                           // doesnt know it.
    }
    return 0;
}

/* I thought about this solution: to inherit from IAB instead of A for the mixed 
   classes, but it doesnt compile, 
stating "the following virtual functions are pure within AB1: virtual void IB::bar()"
which is inherited through B1 though, and i cant figure out where to add the virtual
inheritence. Example:

class IAB : public A, public IB
{
//  virtual void foo () = 0; // I actually dont need them to be declared here again,
//  virtual void bar () = 0; // do i? 

};

class AB1 : public B1, public IAB
{
    void foo() {A::foo(); B1::bar();}
};
*/

Вопрос в том, как получить комбинацию обоих пакетов A и B, чтобы оба интерфейса были доступны из одного контейнера, а все детали реализации из A и B все еще наследуются?

1 ответ

Решение

Очевидное решение - создать комбинированный интерфейс:

class IAB : public virtual IA, public virtual IB
{
};

, иметь свой AB1 а также AB2 извлечь из него (в дополнение к их текущим выводам), и сохранить IAB* в векторе.

Это означает, что B1 а также B2 должен также происходить практически изIB; учитывая направление, кажется, что дела идут, A вероятно, следует также получить практически из IA,

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

Другие вопросы по тегам