override

override 是 C++11 引入的一个关键字,override 的作用是在派生类中显式地声明某个函数是用于重写基类的虚函数。它不仅仅是一个语法标记,更重要的是提供了编译时的错误检查功能,确保程序员确实按照预期在派生类中重写了基类的函数。如果没有正确地重写函数(如参数类型不匹配),编译器会抛出错误。

使用场景

当你在派生类中希望重写基类的虚函数时,通常在函数声明后加上 override 关键字。这可以确保:

  1. 基类中的函数是虚函数。
  2. 派生类中的函数正确地重写了基类中的函数(函数签名要完全一致)。

用法示例

假设有一个基类 Base,其中定义了一个虚函数 virtual void func()

class Base {
public:
    virtual void func() {
        std::cout << "Base function" << std::endl;
    }
};

如果要在派生类 Derived 中重写该虚函数,可以使用 override 关键字:

class Derived : public Base {
public:
    void func() override {
        std::cout << "Derived function" << std::endl;
    }
};

在这个例子中,Derived 类的 func 函数明确标记为重写了 Base 类的 func 函数。如果派生类中的函数签名与基类不匹配,编译器会报错。例如:

class Derived : public Base {
public:
    void func(int x) override {  // 错误:签名与基类不匹配
        std::cout << "Derived function" << std::endl;
    }
};

这个错误会被及时发现,因为 func(int x) 的签名与基类的 func() 不匹配,编译器会指出这是不合法的重写。

关键点总结

  • override 用于确保虚函数的正确重写,避免签名不匹配问题。
  • 它能提高代码的可读性和可维护性,便于他人理解代码中的继承关系。

下面通过一个具体的代码实例展示了 override 的使用,以及它在派生类中防止函数签名不匹配和提高代码可读性等方面的作用。

示例代码

#include <iostream>

// 基类
class Animal {
public:
    // 基类中的虚函数
    virtual void makeSound() const {
        std::cout << "Animal makes a sound." << std::endl;
    }

    // 基类中的虚函数
    virtual void move(int distance) const {
        std::cout << "Animal moves " << distance << " meters." << std::endl;
    }
};

// 派生类
class Dog : public Animal {
public:
    // 正确重写基类中的 makeSound 函数
    void makeSound() const override {
        std::cout << "Dog barks." << std::endl;
    }

    // 错误重写:这里 move 函数的参数类型不匹配
    // void move(double distance) const override {  // 如果这样写,编译器会报错,因为参数类型与基类不匹配
    //     std::cout << "Dog runs " << distance << " meters." << std::endl;
    // }

    // 正确重写基类中的 move 函数
    void move(int distance) const override {
        std::cout << "Dog runs " << distance << " meters." << std::endl;
    }

    // 自己定义的新函数,不重写基类
    void wagTail() const {
        std::cout << "Dog wags its tail." << std::endl;
    }
};

int main() {
    Animal* animal = new Animal();
    Animal* dog = new Dog();

    // 调用基类的虚函数
    animal->makeSound();  // 输出: Animal makes a sound.
    dog->makeSound();     // 输出: Dog barks. (派生类重写的版本)

    animal->move(10);     // 输出: Animal moves 10 meters.
    dog->move(20);        // 输出: Dog runs 20 meters. (派生类重写的版本)

    // 直接调用派生类的非虚函数
    // animal->wagTail();  // 错误,Animal 没有定义 wagTail
    static_cast<Dog*>(dog)->wagTail();  // 输出: Dog wags its tail.

    delete animal;
    delete dog;

    return 0;
}

代码解释

  1. 基类 Animal

    • 基类 Animal 定义了两个虚函数 makeSound()move(int distance),它们可以被派生类重写。
  2. 派生类 Dog

    • Dog 类通过 override 关键字正确重写了基类的虚函数 makeSound()move(int distance)
    • 如果尝试使用不匹配的参数类型(例如 move(double distance)),编译器会报错,这就是 override 提供的安全性保证。
  3. 虚函数调用

    • main() 函数中,基类指针 animal 和派生类指针 dog 指向了不同的对象。
    • 当调用虚函数 makeSound()move() 时,dog 对象调用的是 Dog 类中重写的函数,显示了狗的行为,而不是基类的默认行为。
  4. 派生类自定义函数

    • Dog 类还定义了自己的函数 wagTail(),它不是重写基类中的函数,无法通过基类指针调用。

编译器报错示例

如果 Dog 类中的 move 函数定义为:

void move(double distance) const override { // 错误:函数签名不匹配 std::cout << "Dog runs " << distance << " meters." << std::endl; }

编译器会报错,因为基类中的 move 函数参数是 int 类型,而这里的参数是 double 类型。使用 override 关键字后,编译器会检查重写是否正确,从而帮助程序员发现这些潜在的错误。

总结,通过这个代码实例可以看到,override 能确保派生类中的函数与基类虚函数签名匹配,防止因疏忽引发的重写错误,并且提高代码的可读性和安全性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值