Pregunta

I stumbled upon the following problem: I have two packages A and B working fine for each own. Each has its own interface and his own implementation. Now i made a package C combining a adapter of A with a concrete Implemenation of B. C actually only implements the Interface of A and is only inheritating and using the Interface of B internally for now. Most of the times that was enough to have only access to the Interface A from a Container, but now i need the methods from B accessible too. Here is the simple example:

//----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();}
};
*/

The question is, how to achieve a combination of both Packages A and B, so that both Interfaces are accessible from one Container, while all the implementation details from A and B still get inherited?

¿Fue útil?

Solución

The obvious solution is to create a combined interface:

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

, have your AB1 and AB2 derive from it (in addition to their current derivations), and keep IAB* in the vector.

This means that B1 and B2 must also derive virtually from IB; given the direction things seem to be going, A should probably also derive virtually from IA.

There are strong arguments that inheritance of an interface should always be virtual. Without going that far: if a class is designed to be derived from, and it has bases, those bases should be virtual (and arguably, if a class is not designed to be derived from, you shouldn't derive from it). In your case, you're using the classic mixin technique, and generally, the simplest solution is for all inheritance in a mixin to be virtual.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top