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
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.
};
Is it possible in C++ to have one vtable shared by multiple classes?
As per my understanding if a class is having a virtual function then it will generate a vtable.So every class should have its own vtable.
Vtables are an implementation detail. C++ doesn't have vtables, it has virtual functions. Vtables just happen to be the most common (if not only) implementation, and the details differ.
What is it that you actually want to achieve?
Polymorphism could be implemented several ways. And vtables could also be implemented several ways. But usually in following case
class A {
virtual foo(){}
}
class B : public A {
virtual foo(){}
}
class C : public B {
void fooNonVirtual(){};
}
classes B and C should have the same vtable.
Example:
A *a = new A;
B *b = new B;
C *c = new C;
a->foo(); // A::foo is called
((A*)b)->foo(); // B::foo is called
((A*)c)->foo(); // B::foo is called
foo for a and b calls different methods because A and B has different vtables. For b and c the same method is called. So compiler could make some optimization and create only one vtable for B and C classes.
fooNonVirtual is not virtual and do not require vtables at all.
You can do
typedef some::Class AnotherClass;
and then these classes would share.
Also, inheritance could - at least theoretically - result in the sharing of vtables.
A vtable is basically a table of virtual functions, so if the two classes have the same virtual functions, it seems pretty straightforward to share the vtable.
struct Class1
{
virtual void func() { /* whatever */ }
};
struct Class2 // can share the vtable with Class1
{
void nonvirtual_func() { /* whatever */ }
};
However, vtable may also contain other info (e.g. the stuff returned by typeid) - in this case, sharing the vtable is impossible. Some compilers have an option to disable RTTI and typeid - so that setting may affect the answer to the question.
It's not really clear what is being asked. A single class may
have many different vtable, depending on how it is used. And
the compiler will merge the vtables of several classes in
a hierarchy. For example:
struct VB { virtual ~VB() = default; };
struct L : virtual VB {};
struct R : virtual VB {};
struct D : L, R {};
In this scenario, the vtable for VB will be different
depending on whether you instantiate an L, and R or a D.
On the other hand, in an object with the most derived type D,
both D and the base class L will probably share the same
vtable.
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 made a test code as following:
#include <iostream>
using namespace std;
#ifndef interface
#define interface struct
#endif
interface Base
{
virtual void funcBase() = 0;
};
interface Derived1 : public Base
{
virtual void funcDerived1() = 0;
};
interface Derived2 : public Base
{
virtual void funcDerived2() = 0;
};
interface DDerived : public Derived1, public Derived2
{
virtual void funcDDerived() = 0;
};
class Implementation : public DDerived
{
public:
void funcBase() { cout << "base" << endl; }
void funcDerived1() { cout << "derived1" << endl; }
void funcDerived2() { cout << "derived2" << endl; }
void funcDDerived() { cout << "dderived" << endl; }
};
int main()
{
DDerived *pObject = new Implementation;
pObject->funcBase();
return 0;
}
The reason I wrote this code is to test if the function funcBase() can be called in an instance of DDerived or not. My C++ complier (Visual Studio 2010) gave me a compile error message when I tried to compile this code. In my opinion, there is no problem in this code because it is certain that the function funcBase() will be implemented (thus overriden) in some derived class of the interface DDerived, because it is pure virtual. In other words, any pointer variable of type Implementation * should be associated with an instance of a class deriving Implentation and overriding the function funcBase().
My question is, why the compiler give me such an error message? Why the C++ syntax is defined like that; i.e., to treat this case as an error? How can I make the code runs? I want to allow multiple inheritance of interfaces. Of course, if I use "virtual public" or re-declare the function funcBase() in Implementation like
interface DDerived : public Derived1, public Derived2
{
virtual void funcBase() = 0;
virtual void funcDDerived() = 0;
};
then everything runs with no problem.
But I don't want to do that and looking for more convenient method, because virtual inheritance may degrade the performance, and re-declaration is so tedious to do if inheritance relations of classes are very complex. Is there any methods to enable multiple inheritance of interfaces in C++ other than using virtual inheritance?
As you've defined it, your object structure looks like this:
The important point here is that each instance of Implementation contains two entirely separate instances of Base. You're providing an override of Base::funcBase, but it doesn't know whether you're trying to override funcBase for the Base you inherited through Derived1, or the Base you inherited through Derived2.
Yes, the clean way to deal with this is virtual inheritance. This will change your structure so there's only one instance of Base:
This is almost undoubtedly what you really want. Yes, it got a reputation for performance problems in the days of primitive compilers and 25 MHz 486's and such. With a modern compiler and processor, you're unlikely to encounter a problem.
Another possibility would be some sort of template-based alternative, but that tends to pervade the rest of your code -- i.e., instead of passing a Base *, you write a template that will work with anything that provides functions A, B, and C, then pass (the equivalent of) Implementation as a template parameter.
The C++ language is designed in such a way that in your first approach without virtual inheritance there will be two parent copies of the method and it can't figure out which one to call.
Virtual inheritance is the C++ solution to inheriting the same function from multiple bases, so I would suggest just using that approach.
Alternately have you considered just not inheriting the same function from multiple bases? Do you really have a derived class that you need to be able to treat as Derived1 or Derived2 OR Base depending on the context?
In this case elaborating on a concrete problem rather than a contrived example may help provide a better design.
DDerived *pObject = new Implementation;
pObject->funcBase();
This creates a pointer of type DDerived to a Implementation. When you are using DDerived you really just have a pointer to an interface.
DDerived does not know about the implementation of funcBase because of the ambiguity of having funcBase being defined in both Derived1 and Derived2.
This has created a inheritance diamond which is what is really causing the problem.
http://en.wikipedia.org/wiki/Diamond_problem
I also had to check on the interface "keyword" you have in there
it's an ms-specific extension that's recognised by visual studio
I think C++ Standard 10.1.4 - 10.1.5 can help you to understand the problem in your code.
class L { public: int next; /∗ ... ∗/ };
class A : public L { /∗...∗/ };
class B : public L { /∗...∗/ };
class C : public A, public B { void f(); /∗ ... ∗/ };
10.1.4 A base class specifier that does not contain the keyword virtual,
specifies a non-virtual base class. A base class specifier that
contains the keyword virtual, specifies a virtual base class. For each
distinct occurrence of a non-virtual base class in the class lattice
of the most derived class, the most derived object (1.8) shall contain
a corresponding distinct base class subobject of that type. For each
distinct base class that is specified virtual, the most derived object
shall contain a single base class subobject of that type. [ Example:
for an object of class type C, each distinct occurrence of a
(non-virtual) base class L in the class lattice of C corresponds
one-to-one with a distinct L subobject within the object of type C.
Given the class C defined above, an object of class C will have two
subobjects of class L as shown below.
10.1.5 In such lattices, explicit qualification can be used to specify which
subobject is meant. The body of function C::f could refer to the
member next of each L subobject: void C::f() { A::next = B::next; } //
well-formed. Without the A:: or B:: qualifiers, the definition of C::f
above would be ill-formed because of ambiguity
So just add qualifiers when calling pObject->funcBase() or solve ambiguity in another way.
pObject->Derived1::funcBase();
Updated: Also very helpful reading will be 10.3 Virtual Functions of Standard.
Have a nice weekend :)
First off I apologize if there is another post out there that answers this, all the similar posts I found dealt with diamond inheritance schemes or defined functions, which this does not.
In short, I'm wondering if it is possible to have one class inherit from two other classes where both child classes has a function with the same name and arguments but it is defined in one child class, and pure-virtual in another. Furthermore if I can do this, would invoking the function on the pure-virtual/abstract class end up calling the defined function on the other child class with minimal changes to the derived class?
Example:
class A
{
public:
virtual void Set(int X) = 0;
};
class B
{
public:
virtual void Set(int X);
};
class AB : public A, public B
{
//other methods not relevant to example go here
};
int main(int argc, char **argv)
{
int Y = 5;
A* ObjectA = new AB();
ObjectA->Set(Y);
return 0;
}
So far my attempts to compile this basic example have been met with errors that say:
'AB' : cannot instantiate abstract class
due to following members:
'void A::Set(int)' : is abstract
When doing my own research I couldn't find a clear answer, but based on other questions that dealt with related topics I found that using a "using B::Set" in class AB may help with this. But when I try adding it to the AB class definition, the error persists.
Is there any way I can make this work?
If you had 2 normal functions Set in A and B, then using B::Set would tell the compiler that if you have object of class AB and call method Set of that object, B::Set will be invoked, if AB::Set not defined explicitly.
Your situation is different. You have pure virtual function A::Set that leads A to be abstract class. As AB does not override A::Set, AB becomes abstract too, that is why you cannot instantiate it.
What you can do here
You can implement AB::set to call B::Set:
class AB : public A, public B
{
public:
void Set(int x) { return B::Set(x); }
};
Also I do not recommend same method names for base classes, as I do not recommend multiple inheritance, try use aggregation instead.
Have you tried implementing the method:
class AB : public A, public B
{
void Set(int X) {}
};
The reason it's not working is that A::Set() is pure virtual. I.e. it has no implementation. But you try to call it. You have to override it in the derived class in order to be able to instantiate the derived class.
The using doesn't work in your case because you have an A*, so there's no ambiguity for the compiler.
In case you had:
AB* ObjectA = new AB();
ObjectA->Set(Y);
you'd have to use using inside the declaration of AB to resolve the ambiguity.
Class AB derives from A, A has a pure virtual method making the class abstract, AB must implement any pure virtual methods declared in a base class in order to be instantiated.
I would try to avoid multiple inheritance it can cause many headaches and there are generally better ways to solve a problem, for instance in this example I don't understand the point in deriving from both A and B, if B shares and in fact implements the same interface as A then surely B should be derived from A.