Hi,

I have the following code. and it works fine.

class base
{
public:
    base() {};
    virtual ~base() {};
    virtual void foo() = 0;
    virtual void boo() = 0;
};

class derive2 : public virtual base
{
 public:
        derive2() {};
        virtual ~derive2() {};
        virtual void foo() {};
};

class derive3 : public virtual base
{
 public:
        derive3() {};
        virtual ~derive3() {};
        virtual void boo() {};
};

class derive : public derive2, protected derive3
{
public:
    derive(){};
    virtual ~derive(){};
};

int main()
{
    derive d;
    return 0;
}

However, if I modify the derive2 and derive3 class as below

class derive2 : public virtual base
{
 public:
        derive2() {};
        virtual ~derive2() {};
        virtual void foo() {};
        virtual void boo() {};
};

class derive3 : public virtual base
{
 public:
        derive3() {};
        virtual ~derive3() {};
        virtual void foo() {};
        virtual void boo() {};
};

then compilation errors are found;

no unique final overrider for 'virtual void base::boo()' in 'derive'
no unique final overrider for 'virtual void base::foo()' in 'derive'

can anyone tell me what is wrong?
Thank you.

Michael

You've introduced a virtual inheritance ambiguity. Since those member functions are virtual from the base, and both sides of this triangle you've created override them, which of the overrides will be inherited by the bottom of the triangle?

The error is telling you to add a final override in derive:

class derive : public derive2, protected derive3
{
public:
    derive(){};
    virtual ~derive(){};
    virtual void foo() {}
    virtual void boo() {}
};

Narue gave a good explanation of the problem. If you don't want class derive to re-implement both functions, you should be able to do this:

class derive : public derive2, protected derive3
{
public:
    derive();
    derive2::foo;
    derive3::boo;
};

That tells the compiler which terminal version of the function(s) to use.

Just a final comment about this sort of multiple inheritance scenario - avoid it at all costs! You will find yourself dealing with tonnes of gnarly bugs, and if building on multiple platforms or different compiler versions, subtle issues with those as well. Remember the KISS principle. It definitely applies here!

As for single trace multiple inheritance (no common base classes), that is a very powerful feature of C++, and one to use to express specific implementations of general abstractions. An example would be that of a storage adapter. Sometimes, the storage adapter might be a remote server that communicates with messages, such as SOAP. Other times, it may be a local SQL database, or a flat file. Each of these storage adapter types can be derived from the StorageAdapter base class, which has the interfaces you need, but behaves very differently internally. So, a persistent class can have a static member that is a pointer to a generic StorageAdapter, yet when the class asks the adapter to store it, it gets handled appropriately, being marshaled as an XML SOAP message in one case and sent to a remote server, to executing SQL statements directly to a local database server, to writing the contents of the object out to a flat file in whatever format it chooses. The object doesn't need to know anything about that. It's store() method can simply pass its 'this' pointer to the storage adapter, and that then deals with all the twiddly bits.

An abstract class is one whose object cannot be created and inheritance is the property in which super class inherit the property of base class.

You've introduced a virtual inheritance ambiguity. Since those member functions are virtual from the base, and both sides of this triangle you've created override them, which of the overrides will be inherited by the bottom of the triangle?

The error is telling you to add a final override in derive:

class derive : public derive2, protected derive3
{
public:
    derive(){};
    virtual ~derive(){};
    virtual void foo() {}
    virtual void boo() {}
};

Thank you Narue. I got it.

Narue gave a good explanation of the problem. If you don't want class derive to re-implement both functions, you should be able to do this:

class derive : public derive2, protected derive3
{
public:
    derive();
    derive2::foo;
    derive3::boo;
};

That tells the compiler which terminal version of the function(s) to use.

Just a final comment about this sort of multiple inheritance scenario - avoid it at all costs! You will find yourself dealing with tonnes of gnarly bugs, and if building on multiple platforms or different compiler versions, subtle issues with those as well. Remember the KISS principle. It definitely applies here!

I still got the same error. it is the same if I use "using".

An abstract class is one whose object cannot be created and inheritance is the property in which super class inherit the property of base class.

You need to pay closer attention to your terminology. An abstract class is one that cannot be independently instantiated, you have the right basic idea there. However, a superclass is the same concept as a base class. A subclass is the same concept as a derived class.

Thus, a sub/derived class inherits from a super/base class.

@OP:
A using statement only makes identifiers from a different scope/namespace visible within the current one, it does not declare them within the current scope. You would have to specifically define the needed function(s). If one of the inherited versions is what you want to run, you'll have to call that version from the derived version of the function:

class derive3 : public derive1, public derive2 {
 private:
   //...
 public:
   //...
   virtual void foo() { derive1::foo(); }  //"virtual" not really required, but recommended as good practice
   virtual void bar() { derive2::bar(); }  //"virtual" not really required, but recommended as good practice
   //...
};

Edited 5 Years Ago by Fbody: n/a

This article has been dead for over six months. Start a new discussion instead.