Virtual inheritance error
Hi guys,
I'm using virtual inheritance to solve the "diamond" problem in C++. The following code works fine when compiled with gcc, but does not under Visual C++.
Interface A allows one to print() and clone() the object. Interface B inherits (virtually) from A, and overrides the clone() function to actually return a B*, not merely a A*. Several other classes not included here are assumed to inherit virtually from A.
The C class implements B.
Let c be an instance of class C. c can print and clone itself as expected.
However when c is cast to B*, it can print itself but cloning does NOT work. The problem is when calling C::clone(), the 'this' pointer is 2 bytes away from its correct address.
When using regular inheritance (from B to A), it works. When B does not override clone(), it works as well.
Am I missing something...? Or is my implementation somehow illegal?
Thanks!
Ives
Code:
#include <iostream>
using namespace std;
// Base Interface A
class InterfaceA
{
public:
virtual void print() = 0;
virtual InterfaceA* clone() = 0;
};
// Interface B inherits virtually from A
class InterfaceB : public virtual InterfaceA
{
public:
virtual InterfaceB* clone() = 0;
};
// C implements interface B
class ConcreteC : public InterfaceB
{
public:
ConcreteC(int _c) : c(_c) { }
virtual void print()
{
cout << c << endl;
}
virtual ConcreteC* clone()
{
return new ConcreteC(c);
}
private:
int c;
};
int main(int argc, char *argv[])
{
ConcreteC *c = new ConcreteC(1);
c->print(); // prints "1"
ConcreteC *c_clone = c->clone();
c_clone->print(); // prints "1"
InterfaceB *b = c;
b->print(); // prints "1"
InterfaceB *b_clone = b->clone(); // doesn't work!
b_clone->print(); // oups! prints some random number
}
Re: Virtual inheritance error
This should not compile.
You have not provided implementation for InterfaceA* clone() and InterfaceB* clone().
And so ConcreteC is still an abstract class and is not instantiatable.
Re: Virtual inheritance error
Thanks Superman,
I thought overriding virtual functions with a compatible (or covariant?) return type was actually common practice in C++.
The code does compile (even if it shouldn't) with VC++ 2008 but generates an error at runtime. So my guess is that mixing both virtual inheritance and covariant return types (on virtual functions) is not supported under VC++.
Does that sound right?
Regards,
Ives
Re: Virtual inheritance error
Quote:
Originally Posted by IvesRogne
I thought overriding virtual functions with a compatible (or covariant?) return type was actually common practice in C++.
You are correct; _Superman_ made a mistake when reading your code.
Quote:
Originally Posted by IvesRogne
The code does compile (even if it shouldn't) with VC++ 2008 but generates an error at runtime. So my guess is that mixing both virtual inheritance and covariant return types (on virtual functions) is not supported under VC++.
I do not have MSVC9 on this computer to check for myself, but a quick check with the MinGW port of g++ 3.4.5 shows that I do not get the problem that you described, so you might be correct, though I have my doubts.
By the way, InterfaceA should have a virtual destructor (but you neglected to use delete in your example anyway), and you do not actually need that dynamic_cast in your example.
Re: Virtual inheritance error
Hi laserlight,
Quote:
Originally Posted by laserlight
By the way, InterfaceA should have a virtual destructor (but you neglected to use delete in your example anyway), and you do not actually need that dynamic_cast in your example.
Thanks for pointing out the virtual destructor, I actually overlooked the problem in my application. The dynamic_cast are indeed unnecessary.
I took a closer look in M$ feedback forums and it seems that the virtual base class / covariant virtual functions is not a winning combo.
http://social.msdn.microsoft.com/For...d-c85670f8f304
"Judging from earlier feedback articles, the combination of covariant return types and virtual base classes is a lethal one. Most of these are closed as "won't fix""
So I'll resort to another less-elegant solution.
Thanks