CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 5 of 5
  1. #1
    Join Date
    Apr 2005
    Location
    Quebec
    Posts
    13

    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
    }
    Last edited by IvesRogne; October 15th, 2009 at 10:27 AM. Reason: Removed unnecessary dynamic_cast

  2. #2
    Join Date
    Feb 2009
    Location
    India
    Posts
    444

    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.
    «_Superman
    I love work. It gives me something to do between weekends.

    Microsoft MVP (Visual C++)

  3. #3
    Join Date
    Apr 2005
    Location
    Quebec
    Posts
    13

    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

  4. #4
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    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.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  5. #5
    Join Date
    Apr 2005
    Location
    Quebec
    Posts
    13

    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

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured