In C++, what is a virtual base class?

后端 未结 11 2146
一个人的身影
一个人的身影 2020-11-22 00:55

I want to know what a \"virtual base class\" is and what it means.

Let me show an example:

class Foo
{
public:
    void DoSomething() { /* .         


        
11条回答
  •  孤街浪徒
    2020-11-22 01:11

    Diamond inheritance runnable usage example

    This example shows how to use a virtual base class in the typical scenario: to solve diamond inheritance problems.

    Consider the following working example:

    main.cpp

    #include 
    
    class A {
        public:
            A(){}
            A(int i) : i(i) {}
            int i;
            virtual int f() = 0;
            virtual int g() = 0;
            virtual int h() = 0;
    };
    
    class B : public virtual A {
        public:
            B(int j) : j(j) {}
            int j;
            virtual int f() { return this->i + this->j; }
    };
    
    class C : public virtual A {
        public:
            C(int k) : k(k) {}
            int k;
            virtual int g() { return this->i + this->k; }
    };
    
    class D : public B, public C {
        public:
            D(int i, int j, int k) : A(i), B(j), C(k) {}
            virtual int h() { return this->i + this->j + this->k; }
    };
    
    int main() {
        D d = D(1, 2, 4);
        assert(d.f() == 3);
        assert(d.g() == 5);
        assert(d.h() == 7);
    }
    

    Compile and run:

    g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
    ./main.out
    

    If we remove the virtual into:

    class B : public virtual A
    

    we would get a wall of errors about GCC being unable to resolve D members and methods that were inherited twice via A:

    main.cpp:27:7: warning: virtual base ‘A’ inaccessible in ‘D’ due to ambiguity [-Wextra]
       27 | class D : public B, public C {
          |       ^
    main.cpp: In member function ‘virtual int D::h()’:
    main.cpp:30:40: error: request for member ‘i’ is ambiguous
       30 |         virtual int h() { return this->i + this->j + this->k; }
          |                                        ^
    main.cpp:7:13: note: candidates are: ‘int A::i’
        7 |         int i;
          |             ^
    main.cpp:7:13: note:                 ‘int A::i’
    main.cpp: In function ‘int main()’:
    main.cpp:34:20: error: invalid cast to abstract class type ‘D’
       34 |     D d = D(1, 2, 4);
          |                    ^
    main.cpp:27:7: note:   because the following virtual functions are pure within ‘D’:
       27 | class D : public B, public C {
          |       ^
    main.cpp:8:21: note:    ‘virtual int A::f()’
        8 |         virtual int f() = 0;
          |                     ^
    main.cpp:9:21: note:    ‘virtual int A::g()’
        9 |         virtual int g() = 0;
          |                     ^
    main.cpp:34:7: error: cannot declare variable ‘d’ to be of abstract type ‘D’
       34 |     D d = D(1, 2, 4);
          |       ^
    In file included from /usr/include/c++/9/cassert:44,
                     from main.cpp:1:
    main.cpp:35:14: error: request for member ‘f’ is ambiguous
       35 |     assert(d.f() == 3);
          |              ^
    main.cpp:8:21: note: candidates are: ‘virtual int A::f()’
        8 |         virtual int f() = 0;
          |                     ^
    main.cpp:17:21: note:                 ‘virtual int B::f()’
       17 |         virtual int f() { return this->i + this->j; }
          |                     ^
    In file included from /usr/include/c++/9/cassert:44,
                     from main.cpp:1:
    main.cpp:36:14: error: request for member ‘g’ is ambiguous
       36 |     assert(d.g() == 5);
          |              ^
    main.cpp:9:21: note: candidates are: ‘virtual int A::g()’
        9 |         virtual int g() = 0;
          |                     ^
    main.cpp:24:21: note:                 ‘virtual int C::g()’
       24 |         virtual int g() { return this->i + this->k; }
          |                     ^
    main.cpp:9:21: note:                 ‘virtual int A::g()’
        9 |         virtual int g() = 0;
          |                     ^
    ./main.out
    

    Tested on GCC 9.3.0, Ubuntu 20.04.

提交回复
热议问题