飞道的博客

C++ override关键字的避坑妙用

407人阅读  评论(0)

C++ 11带来了override关键字,用于成员函数声明之后,表示这是个虚函数,并重写了基类里的虚函数。

本文讲解override的一个妙用,用于避免掉进坑里。


一 坑的描述及解决

避坑1

下面是两个类,一个基类和一个子类,

class A
{
   
public:
    virtual bool foo() {
    };
};
 
class B : public A
{
   
public:
    void foo() const
    {
   
        std::cout << "hello world\n";
    }
};

然后我们写个main函数去使用class B,

int main(void)
{
   
    A * ptr = new B();
    ptr->foo();
    return 0;
}

编译没问题,然后运行,结果什么都没有打印…

为什么呢?类A和B的定义,乍一看基类的函数foo被子类重写了,其实没有,因为子类函数声明后面加了const,这样这2个foo()函数的signature就不匹配。

程序运行时在子类中没有找到重写的foo()函数 (因为指针的类型是基类),这样就会去调用基类中的foo()函数。

如何避免?通过在子类foo()函数后面加上override,如下,

class B : public A
{
   
public:
    void foo() const override
    {
   
        std::cout << "hello world\n";
    }
};

这样编译时就会报错,提示并没有覆盖基类中的foo()函数,

避坑2

假如基类中的函数忘记写virtual,子类中函数重写了该函数(本意是想子类重写基类中的虚函数),

class A
{
   
public:
    void bar() {
   }
};
 
class B : public A
{
   
public:
    
    void bar() 
    {
   
        std::cout << "hehe\n";
    }
};

下面是main函数,

int main(void)
{
   
    A * ptr = new B;
    
    ptr->bar();
    
    return 0;
}

编译没问题,运行后发现什么都没有打印…
原理也比较简单,类B的bar()函数并不在虚函数表里,这样使用基类指针去调用时就无法找到B的bar()函数,只能去执行A的bar()函数。

但是如果在B的bar()函数声明后加上override,编译时就会给出错误了,

class B : public A
{
   
public:
    
    void bar() override
    {
   
        std::cout << "hehe\n";
    }
};

提示如下,

这样顺着这个就回去查看基类,就可以发现基类函数没有加virtual关键字。


二 总结

这里用该链接里的回答来总结下override的用处,

The override keyword serves two purposes:

  1. It shows the reader of the code that “this is a virtual method, that is overriding a virtual method of the base class.”
  2. The compiler also knows that it’s an override, so it can “check” that you are not altering/adding new methods that you think are overrides.

转载:https://blog.csdn.net/whahu1989/article/details/117535968
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场