Say we have a concrete class A, and an abstract class B.
Consider a concrete C, that inherits from both A and B, and implements B:
class C : public A, public B
{
/* implementation of B and specific stuff that belongs to C */
};
Now I define a function which signature is void foo(B* b);
This is my code, I can assume that every pointers to B are both A and B.
In foo's definition, how to get a pointer to A?
A nasty but working trick is to align back pointers like so:
void foo(B* b)
{
A* a = reinterpret_cast<A*>(reinterpret_cast<char*>(b) - sizeof(A));
// now I can use all the stuff from A
}
Keep in mind that C does not have a super type and actually, there are many classes akin to C which only are A and B. Feel free to question both my logic and this sample of design as well but the question is only concerning pointers alignment.
void foo(B* b)
{
//A* a = reinterpret_cast<A*>(reinterpret_cast<char*>(b) - sizeof(A)); // undefined behaviour!!!!
A* a = dynamic_cast<A*>(b);
if (a)
{
// now I can use all the stuff from A
}
else
{
// that was something else, not descended from A
}
}
Forgot to say: in order to make work dynamic cast both A and B should have virtual function(s) or at least virtual destructors. Otherwise there is no legal way to do that type conversion.
Having a huge set of unrelated classes that both derive from A and B is a very strange design. If there's something that makes A and B always be "used together" you could either merge them or introduce a shim class that only derives from them and then only derive from that class:
class Shim : A, B {};
class DerivedX : Shim {};
and in the latter case you just use static_cast to first downcast from A or B to Shim* and then C++ it will implicitly convert the Shim* pointer to the other class.
If you want to use the functionality of both class A and Class B in your function then you should modify the function to receive C pointers:
void foo(C* c);
And in general you are wrong with you assumption that "every B is an A as well". You could create classes derived from you B interface and not derived from Class A, that's why the compiler won't know that in your specific case "every B is an A".
Expanding on sharptooth's answer (and entering it as an answer, because I can't get formatted code into a comment), you can still use the shim:
class Shim : public virtual A, public virtual B {};
Then:
class Derived1 : public Shim, public virtual A, public virtual B1
{
};
class Derived2 : public Shim, public virtual A, public virtual B2
{
};
B1 and B2 must derive virtually from B.
But I suspect that if you always need to implement both A and
B, you should create a single interface with both, either by
inheriting, or coalising both into a single class; your B1 and
B2 would inherit from that. (The solution with
dynamic_cast, of course, is for the case where the derived
class of B may or may not also derived from A.)
Related
I have this annoying multiple-inheritance diamond of doom with a complicated twist (We're talking about MS COM objects, a detail which will be relevant later) -
Assume an abstract class (interface) A which has some pure virtual methods.
Another abstract class (another interface) B is derived from A and expands it with more pure virtual methods.
Class C is derived from class A and implements all of its abstract methods.
Class D is currently derived from class B, implementing all abstract methods from both A and B.
Right now I have two classes C, D with a lot of copy-pasted code (since most of the required interface resides in class A). I'd like to avoid this by having D inherit from C, however D also inherits from B, which creates a classic diamond of doom issue.
I know this can be solved with virtual inheritance, but here's the twist in the plot: Classes A and B are COM interfaces, defined in an SDK which I cannot modify (i.e. "A.h" and "B.h" are read only). The inheritance from A to B is not virtual and this cannot be modified. I can modify classes C and D, but they must completely adhere to the defined interfaces.
I'd appreciate any creative ideas on how to overcome this.
I'm assuming from the details of the question, that the problem you have is with the functions and not with some member variables of A (which seems to be just an interface).
In that case here are two options that spring to mind.
1) have D own a C rather than inherit from it.
class D : public B
{
public:
virtual int FA()
{
return m_c.FA();
}
private: C m_c;
};
or inherit privately from C
class D : public B, private C
{
public:
virtual int FA()
{
return C::FA();
}
};
Where FA() is some pure virtual function in A
Both cases involve defining a function to implement FA in D, but the actual implementation detail is not duplicated.
The ATL way of resolving this situation:
template <typename Itf>
class IAImpl : public Itf {
// Implement IA methods
};
class C : public IAImpl<IA> {};
class D : public IAImpl<IB> {
// Implement methods of IB that are in addition to IA.
};
I have a class A and class B which inherits from class A. Class B has a variable and a function that are not available in class A. I made a pointer
A* ptr=new B();
So how can ptr access the variable and function that belongs to class B?
Class A simply cannot "see" the functions of class B. Instead, you'd have to use something like a dynamic_cast from A to B, check for null, and then proceed as you like. Here is a nice tutorial to explain this a lot better than I can. Each of the casts have their advantages and disadvantages; learn them well. Also, try to avoid C style casting.
EDIT : Seems I misread the question. The answer is still correct, though. Class A would not be able to "see" the variables of Class B. The casting would still allow you access to them.
You can force the derived class to implement a pure virtual method defined in the base class:
class A
{
public:
virtual void do_things() = 0;
};
class B : public A
{
public:
virtual void do_things()
{
//Implementation
}
};
This way you can call the method implemented by class B through a pointer A*:
A* a_ptr = new B();
//The method implemented in class B will be called
a_ptr->do_things();
You could also make the assumption that a_ptr points to an object of class B. If a_ptr doesn't point to a B the pointer returned by dynamic_cast<B*> will be a nullptr. You can use static_cast<B*> if there are no virtual methods in A.
b_ptr = dynamic_cast<B*>(a_ptr);
b_ptr->do_things;
This way you don't need the pure virtual function in class A.
I have a question regarding composition and inheritance in C++:
I have a base class 'A' and a derived class 'B' ('B' inherits members from 'A'), is it possible use 'B' as a member of 'A' by composition?
As to "A has B member, B derived from A": Practically, you cannot declare such a thing. If class A has a member of type B, then B needs to be declared before A. If B uses A as a base, A must be declared before B.
As to composition, if you wanted to do such a thing, you could have to use indirection (pointer, smart-pointer, etc).
class B;
class A {
B *b;
};
class B : public A {
};
One might argue that (in C++) using pointers is not composition; however, in Java, all Objects are "pointers", so composition is:
class A {
B b;
}
class B extends A {
}
However you may embed a B* field. Hence a const B& should be possible too, and behave like a B. (Mind I am now a sandbox java programmer.)
class B;
class A {
B& b;
};
BTW you might not even embed an A in an A.
I have never used multiple inheritance but while reading about it recently I started to think about how I could use it practically within my code. When I use polymorphism normally I usually use it by creating new derived instances declared as base class pointers such as
BaseClass* pObject = new DerivedClass();
so that I get the correct polymorphic behaviour when calling virtual functions on the derived class. In this way I can have collections of different polymorphic types that manage themselves with regards to behaviour through their virtual functions.
When considering using multiple inheritance, I was thinking about the same approach but how would I do this if I had the following hierarchy
class A {
virtual void foo() = 0;
};
class B : public A {
virtual void foo() {
// implementation
}
};
class C {
virtual void foo2() = 0;
};
class D : public C {
virtual void foo2() {
// implementation
}
};
class E : public C, public B {
virtual void foo() {
// implementation
}
virtual void foo2() {
// implementation
}
};
with this hierarchy, I could create a new instance of class E as
A* myObject = new E();
or
C* myObject = new E();
or
E* myObject = new E();
but if I declare it as a A* then I will lose the polymorphism of the class C and D inheritance hierarchy. Similarly if I declare it as C* then I lose the class A and B polymorphism. If I declare it as E* then I cannot get the polymorphic behaviour in the way I usually do as the objects are not accessed through base class pointers.
So my question is what is the solution to this? Does C++ provide a mechanism that can get around these problems, or must the pointer types be cast back and forth between the base classes? Surely this is quite cumbersome as I could not directly do the following
A* myA = new E();
C* myC = dynamic_cast<C*>(myA);
because the cast would return a NULL pointer.
With multiple inheritance, you have a single object that you can view any of multiple different ways. Consider, for example:
class door {
virtual void open();
virtual void close();
};
class wood {
virtual void burn();
virtual void warp();
};
class wooden_door : public wood, public door {
void open() { /* ... */ }
void close() { /* ... */ }
void burn() { /* ... */ }
void warp() { /* ... */ }
};
Now, if we create a wooden_door object, we can pass it to a function that expects to work with (a reference or pointer to) a door object, or a function that expects to work with (again, a pointer or reference to) a wood object.
It's certainly true that multiple inheritance will not suddenly give functions that work with doors any new capability to work with wood (or vice versa) -- but we don't really expect that. What we expect is to be able to treat our wooden door as either a door than can open and close, or as a piece of wood that can burn or warp -- and that's exactly what we get.
In this case, classes A and C are interfaces, and E implements two
interfaces. (Typically, you wouldn't have intermediate classes C and
D in such a case.) There are several ways of dealing with this.
The most frequent is probably to define a new interface, which is a sum
of A and C:
class AandC : public A, public C {};
and have E derive from this. You'd then normally manage E through a
AandC*, passing it indifferently to functions taking an A* or a
C*. Functions that need both interfaces in the same object will deal
with AandC*.
If the interfaces A and C are somehow related, say C offers
additional facilities which some A (but not all) might want to
support, then it might make sense for A to have a getB() function,
which returns the C* (or a null pointer, if the object doesn't support
the C interface).
Finally, if you have mixins and multiple interfaces, the cleanest
solution is to maintain two independent hierarchies, one for the
interfaces, and another with the implementation parts:
// Interface...
class AandC : public virtual A, public virtual C {};
class B : public virtual A
{
// implement A...
};
class D : public virtual C
{
// implement C...
};
class E : public AandC, private B, private D
{
// may not need any additional implementation!
};
(I'm tempted to say that from a design point of view, inheritance of
interface should always be virtual, to allow this sort of thing in the
future, even if it isn't needed now. In practice, however, it seems
fairly rare to not be able to predict this sort of use in advance.)
If you want more information about this sort of thing, you might want to
read Barton and Nackman. There book is fairly dated now (it describes
pre C++98), but most of the information is still valid.
This should work
A* myA = new E();
E* myC = dynamic_cast<E*>(myA);
myC->Foo2();
C can't cast to A because it isn't an A; it can only cast down to D or E.
Using A* you can make an E* and through that you can always explicitly say things like C::foo() but yes, there is no way for A to implicitly call functions in C that might have overrides or might not.
In weird cases like this, templates are often a good solution because they can allow classes to act as if they have common inheritance even if they don't. For instance, you might write a template that works with anything that can have foo2() invoked on it.
Say I have 4 classes:
class I { public: virtual void X() = 0; };
class A : public virtual I { public: virtual void X() { } };
class B : public I { };
class C : public A, public B { };
I, B and C are abstract, where as A is not. If I simply add virtual to the inheritance of I for B, then A::X() resolves I::X() in C.
However, I cannot change the source of B.
My question: Can I get A::X() to resolve I::X for C without being able to change B? I have tried declaring A and B to be virtual to C to no avail. I am trying to have no redundant code (e.g. have C declare X() { A::X(); }). Any neat hacks?
Also - there are a few questions very much like this, but I couldn't find any talking about using virtual inheritance. Please point to me one if I missed it.
Your problem is with the vtables. In your current code, you have two of them - one in A's I and one in B's I. As long as only A virtually inherits I, you could just as well use regular inheritance and save the overhead. If both virtually inherited I you'd have only one instance of I in C, therefore only one vtable, and A::X could indeed cover the pure virual I::X.
Given you can't change B, the only place you can take care of both vtables is C. In my opinion, the way to go is what you mention - just have C::X forward the call to A::X. There's no code duplication there, and it makes C non-abstract:
class C : public A, public B {
public:
virtual void X() { A::X(); }
};
As for virtual inheritance, there definitively have been some here. But you're welcome to ask...
This is quite good: When virtual inheritance IS a good design?
The problem here is that in C you have two interfaces I. That is why A::x() satisfies
its interface I - but it cannot make not abstract interface I from class B.
For C the only way to have exactly one interface of I - is to change B to derive from I virtually - in this way both I interfaces from A and from B will be merged to one in C. You cannot change B - so the only way is to add this redundant code which you are trying to avoid. I mean define C::X().
The only way I can think of is to compose a B* (or smart variant) into C instead of inheriting from it, and forward the appropriate methods. You can't do it while maintaining the inheritance, because the compiler won't know which I's inheritance chain to follow.