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.
};
Related
Ok, this might be silly question but I can't figure out how to fix my problem.
Let's assume we have 4 classes
class A is a Base class
class B is derived from A with new methods (no override)
class C is derived from A
class D is derived from B (and also from A for inheritance)
my question is: how do I use a method defined in B in D?
If D inherit from B I get "error: member 'xxx' found in multiple base classes of different types"
if D does not inherit from B I get "use of undeclared identifier"
Here's how it's done - based on your description:
class A {
protected:
void foo();
};
class B : public A {
protected:
void bar();
};
class D : public B {
protected:
void baz() { B::bar(); }
};
Note that you should not have D inherit from A directly, except in very specific and rare cases. Inheritance is transitive.
Also, next time, Please post a Minimal, Complete, and Verifiable example and don't make us guess what you mean exactly.
In those cases in which the same method is available from the same subclasses from multiple inheritance paths are the "Diamond Pattern", and you can read about it here.
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.
I'm reading about inheritance and I have a major issue that I haven't been able to solve for hours:
Given a class Bar is a class with virtual functions,
class Bar
{
virtual void Cook();
};
What is the different between:
class Foo : public Bar
{
virtual void Cook();
};
and
class Foo : public virtual Bar
{
virtual void Cook();
};
? Hours of Googling and reading came up with lots of information about its uses, but none actually tell me what the difference between the two are, and just confuse me more.
Functionality wise there is not much difference between the 2 versions. With the case of virtual inheritance, every implementation generally adds a (vptr like) pointer (same as in the case of virtual functions). Which helps to avoid multiple base class copies generated due to multiple inheritance (the diamond inheritance problem)
Also, virtual inheritance delegates the right to call the constructor of its base class. For example,
class Bar;
class Foo : public virtual Bar
class Other : public Foo // <--- one more level child class
So, now Bar::Bar() will be called directly from Other::Other() and also will be placed at the first place among other base classes.
This delegation feature helps in implementing a final class (in Java) functionality in C++03:
class Final {
Final() {}
friend class LastClass;
};
class LastClass : virtual Final { // <--- 'LastClass' is not derivable
...
};
class Child : public LastClass { // <--- not possible to have object of 'Child'
};
Virtual inheritance is only relevant if classes are to inherit from
Foo. If I define the following:
class B {};
class L : virtual public B {};
class R : virtual public B {};
class D : public L, public R {};
Then the final object will only contain one copy of B, shared by both
L and R. Without the virtual, an object of type D would contain
two copies of B, one in L, and one in R.
There is some argument that all inheritance should be virtual (because
in the cases where it makes a difference, that is what you want most of
the time). In practice, however, virtual inheritance is expensive, and
in most cases, not necessary: in a well designed system, most
inheritance will simply be of a concrete class inheriting from one or
more "interfaces"; such a concrete class is usually not designed to be
derived from itself, so there is no problem. But there are important
exceptions: if, for example, you define an interface, and then
extensions to the interface, the extensions should inherit virtually
from the base interface, since a concrete implementation could want to
implement several extensions. Or if you are designing mixins, where
certain classes only implement part of the interface, and the final
class inherits from several of these classes (one per part of the
interface). In the end, the criteron as to whether to inherit virtually
or not isn't too difficult:
if the inheritance isn't public, it probably shouldn't be virtual
(I've never seen an exception), otherwise
if the class is not designed to be a base class, there's no need for
virtual inheritance, otherwise
the inheritance should be virtual.
There are a few exceptions, but the above rules err on the side of
safety; it's usually "correct" to inherit virtually even in cases where
the virtual inheritance isn't necessary.
One final point: a virtual base must always be initialized by the most
derived class, not the class that directly inherits (and declares that
the inheritance is virtual). In practice, however, this is a non-issue.
If you look at the cases where virtual inheritance makes sense, it is
always a case of inheriting from an interface, which will contain no
data, and thus have (only) a default constructor. If you find yourself
inheriting virtually from classes with constructors which take
arguments, it's time to ask some serious questions about the design.
In this case, no difference. Virtual inheritance is related to sharing superclass subobjects instances by derived classes
struct A
{
int a;
};
struct B : public virtual A
{
int b;
}
struct C : public virtual A
{
int c;
};
struct D : public B, public C
{
};
There's a single copy of the member variable a in the instance of D; If A was not a virtual base class, there would be two A subobjects in instance of D.
Virtual function is a function that will probably have different implementation in derived class (although it's not a must).
In your last example is virtual inheritance. Imagine a case where you have two classes (A and B) derived from a base class (let's call it 'Base'). Now imagine a third class C derived from A and B. Without virtual inheritance, the C would contain two copies of 'Base'. That could lead to ambiguity while compiling. The important thing in virtual inheritance is that the parameters for the 'Base' class constructor (if any) MUST be provided in the class C, because such calls from A and B will be ignored.
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.)
The net is overflowing with explanations of the "dreaded diamond problem".
So is StackOverflow. I think I understand that bit, but I fail to translate that knowledge into comprehending something similar yet different.
My question begins as a pure C++ question, but the answer might well branch over into MS-COM specifics. The general problem question goes:
class Base { /* pure virtual stuff */ };
class Der1 : Base /* Non-virtual! */ { /* pure virtual stuff */ };
class Der2 : Base /* Non-virtual! */ { /* pure virtual stuff */ };
class Join : virtual Der1, virtual Der2 { /* implementation stuff */ };
class Join2 : Join { /* more implementation stuff + overides */ };
This is not the classic diamond solution. Exactly what does "virtual" do here?
My real problem is trying to understand a discussion over at our friends' place at CodeProject. It involves a custom class for creating a transparent container for the Flash player.
I thought I would try this place for fun. It turns out that the following declaration crashes your app, with version 10 of the Flash player.
class FlashContainerWnd: virtual public IOleClientSite,
virtual public IOleInPlaceSiteWindowless,
virtual public IOleInPlaceFrame,
virtual public IStorage
Debugging shows that when entering the function implementations (QueryInterface etc), from different callers, I get different "this"-pointer values for different calls.
But removing "virtual" does the trick! No crashes, and same "this"-pointer.
I would like to clearly understand exactly what is going on. Thanks a lot.
Cheers
Adam
The virtual inheritance in the first example don't do anything. I would wager that they compile to the same code if they were removed.
The virtually inherited class just flag the compiler that it should merge later versions of Der1 or Der2. Since only one of each appears in the inheritance tree nothing is done. The virtuals have no effect on Base.
auto p = new Join2;
static_cast<Base*>(static_cast<Der1*>(p)) !=
static_cast<Base*>(static_cast<Der2*>(p))
The virtual inheritance only effects the next inherited class, and only for instances that have been delcared virtual. This is backward from what you would expect, but it's a limitation on the way classes are compiled.
class A {};
class B : virtual public A {};
class C : virtual public A {};
class D : public A {};
class E : virtual public A, public B, public C, public D {};
class F : public A, public B, public C, public D {};
F::A != F::B::A or F::C::A or F::D::A
F::B::A == F::C::A
F::D::A != F::B::A or F::C::A or F::A
E::B::A == E::C::A == E::A
E::D::A != E::B::A or E::C::A or E::D::A
One of the reasons A must be marked virtual in C and B instead of E or F is that C and B need to know not to call A's constructor. Normally they would have initialize each of their copies. When they are involved in diamond inheritance they wont. But you cant recompile B and C to not construct A. That means C and B have to know ahead of time to create constructor code where A's constructor is not called.
I think the issue with your COM example is that by adding the virtual keyword you are saying that all the IOle* interfaces share a common IUnknown implementation. In order to implement this the compiler has to create multiple v-tables, hence you different 'this' values depending on the derived class it came down.
COM requires that when you call IQueryInterface on an object for IUnknown that ALL interfaces exposed by the object return the same IUnknown ... which this implementation clearly breaks.
Without the virtual inheritance each IOle* nominally has its own IUnknown implementation. However, since IUnknown is an abstract class, and doesn't have any storage the compiler, and all the IUnknown implementations come from FlashContainerWnd there is only a single implementation.
(OK, so that last bit sounds weak ... perhaps someone with a better grasp of the language rules can explain it more clearly)
It's a bit dated now, but the best reference I have ever come across that concerns C++ internals is Lippman's Inside The C++ Object Model. The exact implementation details may not match your compiler's output, but the understanding it provides is extremely valuable.
Around page 96 there is an explanation of virtual inheritance and it specifically addresses the diamond problem.
I'll leave you to read the details but basically the use of virtual inheritance requires a lookup in the virtual table in order to locate the base class. This is not the case in normal inheritance, where the base class location can be calculated at compile time.
(The last time I took the easy way out and just recommended a book to answer a stack overflow question I got voted up considerably, so let's see if that happens again... :)
I thought I'd just try your example. I came up with:
#include "stdafx.h"
#include <stdio.h>
class Base
{
public:
virtual void say_hi(const char* s)=0;
};
class Der1 : public Base
{
public:
virtual void d1()=0;
};
class Der2 : public Base
{
public:
virtual void d2()=0;
};
class Join : virtual public Der1, virtual public Der2
// class Join : public Der1, public Der2
{
public:
virtual void say_hi(const char* s);
virtual void d1();
virtual void d2();
};
class Join2 : public Join
{
virtual void d1();
};
void Join::say_hi(const char* s)
{
printf("Hi %s (%p)\n", s, this);
}
void Join::d1()
{}
void Join::d2()
{}
void Join2::d1()
{
}
int _tmain(int argc, _TCHAR* argv[])
{
Join2* j2 = new Join2();
Join* j = dynamic_cast<Join*>(j2);
Der1* d1 = dynamic_cast<Der1*>(j2);
Der2* d2 = dynamic_cast<Der2*>(j2);
Base* b1 = dynamic_cast<Base*>(d1);
Base* b2 = dynamic_cast<Base*>(d2);
printf("j2: %p\n", j2);
printf("j: %p\n", j);
printf("d1: %p\n", d1);
printf("d2: %p\n", d2);
printf("b1: %p\n", b1);
printf("b2: %p\n", b2);
j2->say_hi("j2");
j->say_hi(" j");
d1->say_hi("d1");
d2->say_hi("d2");
b1->say_hi("b1");
b2->say_hi("b2");
return 0;
}
It produces the following output:
j2: 00376C10
j: 00376C10
d1: 00376C14
d2: 00376C18
b1: 00376C14
b2: 00376C18
Hi j2 (00376C10)
Hi j (00376C10)
Hi d1 (00376C10)
Hi d2 (00376C10)
Hi b1 (00376C10)
Hi b2 (00376C10)
So, when casting a Join2 to its base classes, you might get different pointers, but the this pointer passed to say_hi() is always the same, pretty much as expected.
So, basically, I cannot reproduce your problem, making it kind of hard to answer your real question.
Regarding wat "virtual" does, I found the article on wikipedia enlightening, though that, too, seems to focus on the diamond problem
As Caspin says, your first example doesn't actually do anything useful. What it will do however, is add a vpointer to tell derivative classes where to find the classes it inherited from.
This fixes any diamonds you may now create (which you don't), but since the class structure is now no longer static, you cannot use static_cast on it any more. I'm unfamiliar with the API involved, but what Rob Walker says about IUnkown may be related to this.
In short, normal inheritance should be used when you need your own baseclass, that shouldn't be shared with 'sibling' classes: (a is a container, b,c,d are parts that each have a container, e combines these parts (bad example, why not use composition?))
a a a
| | |
b c d <-- b, c and d inherit a normally
\ | /
e
While virtual inheritance is for when your baseclass should be shared with them. (a is vehicle, b,c,d are different specializations of vehicle, e combines these)
a
/ | \
b c d <-- b, c and d inherit a virtually
\ | /
d