As per the wiki, which says that[emphasise mine]: Note the code snippet in the quotaion is seen here.

Suppose a pure virtual method is defined in the base class. If a deriving class inherits the base class virtually, then the pure virtual method does not need to be defined in that deriving class. However, if the deriving class does not inherit the base class virtually, then all virtual methods must be defined. The code below may be explored interactively here.

#include <string>
#include <iostream>

class A                     { 
    protected: 
        std::string _msg; 
    public:
        A(std::string x): _msg(x) {} 
        void test(){ std::cout<<"hello from A: "<<_msg <<"\n"; } 
        virtual void pure_virtual_test() = 0; }; 

// since B,C inherit A virtually, the pure virtual method >pure_virtual_test doesn't need to be defined 
class B: virtual public A
{ public: B(std::string x):A("b"){}  };  
class C: virtual public A   {
public: C(std::string x):A("c"){}  }; 

// since B,C inherit A virtually, A must be constructed in each child
// however, since D does not inherit B,C virtually, the pure virtual method in A *must be defined* 
class D: public B,C { 
    public: 
        D(std::string x):A("d_a"),B("d_b"),C("d_c"){}
        void pure_virtual_test() override { std::cout<<"pure virtual hello from: "<<_msg <<"\n"; } }; 

// it is not necessary to redefine the pure virtual method after the
parent defines it class E: public D { 
    public: 
    E(std::string x):A("e_a"),D("e_d"){}   };


int main(int argc, char ** argv){
    D d("d");
    d.test(); // hello from A: d_a
    d.pure_virtual_test(); // pure virtual hello from: d_a

    E e("e"); 
    e.test(); // hello from A: e_a
    e.pure_virtual_test(); // pure virtual hello from: e_a 
}

How to understand the statement in bold in the right way?

It seems that if the deriving class(i.e. class B) does not inherit the base class virtually, then virtual methods can be left undefined.Here is my demo code snippet to support what I say:

#include <string>
#include <iostream>

class A                     { 
    protected: 
        std::string _msg; 
    public:
        A(std::string x): _msg(x) {} 
        void test(){ std::cout<<"hello from A: "<<_msg <<"\n"; } 
        virtual void pure_virtual_test() = 0;
}; 

// Attention: B does not inherit A ***virtually***, the pure virtual method pure_virtual_test doesn't need to be defined, either.
class B:  public A   { public: B(std::string x):A("b"){}  }; 


class D: public B { 
    public: 
        D(std::string x):B("d_b"){}
        void pure_virtual_test() override { std::cout<<"pure virtual hello from: "<<_msg <<"\n"; }
}; 

// it is not necessary to redefine the pure virtual method after the parent defines it
class E: public D { 
    public: 
    E(std::string x):D("e_d"){}  
}; 

int main(int argc, char ** argv){
    D d("d"); 
    d.test(); 
    d.pure_virtual_test();

    E e("e"); 
    e.test(); 
    e.pure_virtual_test();
}
2

There are 2 best solutions below

1
Sam Varshavchik On BEST ANSWER

The description in the wikipedia article is wrong/misleading.

"If the deriving class does not inherit the base class virtually, then all virtual methods must be defined" is only true if the deriving class gets instantiated. A mere declaration, without instantiation, does not require definition of pure virtual methods.

The wikipedia article's claim that "since D does not inherit B,C virtually, the pure virtual method in A must be defined" is simply not true, and the following compiles without any issues, without either D or E instantiating the pure virtual method:

#include <string>
#include <iostream>

class A                     {
    protected:
        std::string _msg;
    public:
        A(std::string x): _msg(x) {}
        void test(){ std::cout<<"hello from A: "<<_msg <<"\n"; }
        virtual void pure_virtual_test() = 0;
};

// since B,C inherit A virtually, the pure virtual method pure_virtual_test doesn't need to be defined
class B: virtual public A   { public: B(std::string x):A("b"){}  };
class C: virtual public A   { public: C(std::string x):A("c"){}  };

class D: public B,C {
    public:
        D(std::string x):A("d_a"),B("d_b"),C("d_c"){}
};

class E: public D {
    public:
    E(std::string x):A("e_a"),D("e_d"){}
};

int main()
{
    return 0;
}

main is left empty, and D and E are declared without issues. Now, if you try to instantiate one or the other, then you're going to have problems.

0
Pete Becker On

The quoted text seems to be referring to a rule called dominance, which leads to a situation where it sort of looks like a virtual function isn't being overridden, even though it is. Here's an example:

struct base {
    virtual void f();
};

struct i1 : base {
    // doesn't override base::f
};

struct i2 : base {
    void f() {} // overrides base::f

struct derived : i1, i2 {
};

With this hierarchy, you can write

derived d;
d.f(); // illegal, because ambiguous:
       // i1::f, inherited from base, or i2::f
i1* p = &d;
p->f(); // calls base::f

Easy enough, right? Now let's make the inheritance from base virtual. Here's where dominance kicks in:

struct base {
    virtual void f();
};

struct i1 : virtual base {
    // doesn't override base::f
};

struct i2 : virtual base {
    void f() {} // overrides base::f

struct derived : i1, i2 {
};

Now there's only one base sub-object, and i2::f overrides base::f, even in i1:

derived d;
d.f();    // calls i2::f
i1* i1p = &d;
i1p->f(); // calls i2::f

Yes, the call i1p->f() calls i2's version of f, even though i1 doesn't know anything about i2. It's only because i1 and i2 are both base classes of derived and both have base as a virtual base that this works. The compiler has to get the code right for this cross-hierarchy call.

Making base::f pure virtual doesn't change the rules about finding its overriders. So with non-virtual inheritance, i1 doesn't override base::f, and derived is an abstract class. But with virtual inheritance, i2::f overrides base::f, and the class derived is not abstract.