Reputation: 655
I have a class D that extends B which extends A. I now want to add a class C that has exactly the same interface as B but provides a different implementation. So I design it as the following:
This is not exactly what I want, as I only need an instance of D to either extend B or C and not both, however, this is only determined at runtime. The problem with the design above is of course that if I call a method in D which is implemented both in B and C, its ambiguous.
So what I would like to have is to create an instance of either B or C at runtime and then cast it into D. Every time an instance of D calls an inherited method it should use the one of its original object.
Do I need to fiddle with typeid and if/else around each method call or is there a more elegant way to do this?
class A{
virtual f1();
virtual f2();
}
class B : public virtual A{
f1();
f2();
f3();
}
class C : public virtual A{
f1();
f2();
f3();
}
class D : public B, public C{
f4(){f1(); f3)};
}
...
D* d = new D();
E* e = new E(d);
e->d->f1();
e->d->f4();
Instances of D are then passed to another class (E) which does stuff with D and therefore, I cannot modify the interface of D.
Upvotes: 0
Views: 1462
Reputation: 20759
C++ is a statically-typed language. Whatever you do with type declaration is elaborated at compile time, hence the inheritance graph of D
cannot be defied at runtime.
What you probably need is to have A
as a polymorphic base (with all relevant method virtual, included the destructor) for both B and C (concrete implementation of that), and D an "owner of an A
", by containing an A* thet will be assigned at D construction to a new B
or new C
depending on input.
D destructor will call delete A
, and now you have to decide about copy and assignment.
My suggestion is not to use an A*, but a std::unique_ptr
(will make the owned object movable between D-s) or std::shared_ptr
.
In case you need each D to have its own A, then let A to have a clone
method (overridden in B and C, to return a new B
and new C
respectively) and call it in D's copy ctor and assign operator.
Upvotes: 0
Reputation: 409432
It seems like D
doesn't need to inherit from A
(or B
or C
) at all. Instead it just needs to call function in either an instance of B
or an instance of C
.
You can implement it something like this:
class A
{
public:
virtual void f1();
virtual void f2();
};
class B : public A;
class C : public A;
class D
{
A* b_or_c;
public:
D(A* a_pointer)
: b_or_c(a_pointer)
{}
void f3()
{
b_or_c->f1();
b_or_c->f2();
}
};
Can be used like this:
B b; // An instance of B
C c; // An instance of C
D d1(&b);
D d2(&c);
d1.f3(); // Will cause `f1` and `f2` in the object `b` to be called
d2.f3(); // Will cause `f1` and `f2` in the object `c` to be called
Upvotes: -1
Reputation: 31962
It sounds like you just want
class A{
virtual void DoMagic() = 0;
};
class B{
virtual void DoMagic(){};
};
class D{
virtual void DoMagic(){};
};
...
bool INeedB = true;//or false
A* a;
if(INeedB){
a= new B();
}else{
a = new C();
}
a->DoMagic(); // will call the appropriate method based on the value of INeedB;
Unless D actually has behavior of its own? Then you can look at decorator pattern, and make D the decorator of an instance of B or C.
Edit: Your D
class doesnt need to inherit any of A
B
or C
at all.
class D{
D(A* aObj):a(aObj){}
void f3(){ a->f1();a->f2();}
A *a;
};
Replace A *a
in above example with D d
Upvotes: 1
Reputation: 17157
I think you're having inheritance the wrong way around, what you do is define all the methods that you want to call on what you call class D as virtual methods in class A, class B and C both have their own implementation of those methods.
Then you use a data structure of type A*, fill that with pointers to objects of type B and C and you call the methods that you need to call on all the objects in the data structure that contains pointers of type A*, the vtable mechanism will then make sure that the implementation of class B or C is used depending on what the actual object's type is.
See What is the difference between a concrete class and an abstract class?
Upvotes: 2