Skip to content

virtual

#include <iostream>
using namespace std;

class A
{
public:
    virtual void v_test() final { cout << "A::v_test" << endl; }
    virtual void v_test(int) { cout << "A::v_test(int)" << endl; }
    void test() { cout << "A::test" << endl; }
};

class B : public A
{
public:
    // cannot override final virtual function
    //void v_test() { cout << "B::v_test" << endl; }
    void v_test(int) final { cout << "B::v_test(int)" << endl; }
    void test() { cout << "B::test" << endl; }
};

// Final Class
class C final : public B
{
public:
    // cannot override final virtual function
    //void v_test() { cout << "C::v_test" << endl; }
    //void v_test(int) { cout << "C::test(int)" << endl; }
    void test() { cout << "C::test" << endl; }
};

class D : public B
{
public:
    // cannot override final virtual function
    // void v_test() { cout << "D::v_test" << endl; }
    // void v_test(int) { cout << "D::test(int)" << endl; }
    void test() { cout << "D::test" << endl; }
};

int main() 
{
    A a;
    B b;
    C c;
    D d;

    A* pa = &a;
    pa->v_test();
    pa->v_test(0);
    pa->test();
    cout << "----------------" << endl;

    pa = &b;
    pa->v_test();
    pa->v_test(0);
    pa->test();
    cout << "----------------" << endl;

    pa = &c;
    pa->v_test();
    pa->v_test(0);
    pa->test();
    cout << "----------------" << endl;

    pa = &d;
    pa->v_test();
    pa->v_test(0);
    pa->test();
    cout << "----------------" << endl;

    A& ref_a = d;
    ref_a.v_test();
    ref_a.v_test(0);
    ref_a.test();
    cout << "----------------" << endl;

    return 0;
}

没有使用virtual声明的基类接口,派生类无法重写该接口,使用基类指针/引用调用时总是调用基类的接口。

C++的认知烦恼

virtual void v_test() final { cout << "A::v_test" << endl; }

这个是C++编译器或者标准中没法避免的语义上的错误,既然定义为抽象接口就是可以重写(override)的,但是语法上又支持使用final来限制重写。

当然,这个本意是想确保子类从父类继承下来的抽象接口不再被改写。