c++c++11virtual-functionslinearization

Why are pure virtual methods not overridden from a different inheritance branch?


I have this, maybe a little bit complex class hierarchy:

class BS {
  public:
    virtual void meth()=0;
};

class BCA : public virtual BS {
};

class BSS : public virtual BS {
};

class BCS : public virtual BCA, public virtual BSS {
};

class BI4 {
  public:
    void meth() {};
};

class BT4 : public virtual BI4, public virtual BSS {
};

class T4 : public virtual BCS, public virtual BT4 {
};

int main() {
  T4 t4;
};

Now the problem is that although the void meth() is available in the inheritance graph, despite this code won't compile:

$ g++ -c t.cc -std=c++11
t.cc: In function ‘int main()’:
t.cc:27:6: error: cannot declare variable ‘t4’ to be of abstract type ‘T4’
   T4 t4;
      ^
t.cc:23:7: note:   because the following virtual functions are pure within ‘T4’:
 class T4 : public virtual BCS, public virtual BT4 {
       ^
t.cc:3:18: note:        virtual void BS::meth()
     virtual void meth()=0;
                  ^
t.cc:3:18: note:        virtual void BS::meth()

It seems to me as if BS somehow wouldn't see the overloaded meth() method through the BS->BCA->BCS->T4->BT4->BI4 chain.
But why? The method is clearly available, the C3 linearization algorithm used by the C++ should be able very clearly find it.


Solution

  • There are two main aspects:

    Example:

    struct Base
    {
        virtual void foo() = 0;
    };
    
    #ifdef GOOD
        struct Impl_foo: virtual Base
        {
            void foo() override {}
        };
    #else
        struct Impl_foo
        {
            virtual void foo() {}
        };
    #endif
    
    struct Abstract_derived: virtual Base
    {};
    
    struct Derived
        : Abstract_derived
        , Impl_foo      // Java-like implementation inheritance.
                        // In C++ called "by dominance".
    {};
    
    auto main()
        -> int
    {
        Derived o;
        o.foo();
    }
    

    Without defining the GOOD macro symbol, this code doesn't compile.