override和final说明符

1. 重载、重写、隐藏

  • 重载: 同名函数,形参表不同(并不包括返回值类型)
  • 重写: 派生类实现了基类相同的虚函数
  • 隐藏: 派生类实现了基类同名(形参表可不同,返回值类型可不同)非虚函数

2. 使用 override 说明符

2.1 作用

它用于明确显示告诉编译器该派生类函数需要重写基类的虚函数,有助于编译器在编译时检查重写是否正确,并给出更清晰的错误提示。

2.2 Demo

基类 Vehicle

#include <iostream>

class Vehicle {
public:
    // 虚函数,允许在派生类中被重写
    virtual void move() {
        std::cout << "Vehicle is moving" << std::endl;
    }

    // 虚析构函数,确保通过基类指针删除派生类对象时能够正确调用派生类的析构函数
    virtual ~Vehicle() {}
};

派生类 Car

class Car : public Vehicle {
public:
    // 使用override关键字显式标记为重写
    void move() override {
        // 重写后的方法体
        std::cout << "Car is moving on the road" << std::endl;
    }
};

使用示例

int main() {
    Vehicle* myVehicle = new Vehicle();
    myVehicle->move(); // 输出: Vehicle is moving

    Car* myCar = new Car();
    myCar->move(); // 输出: Car is moving on the road

    // 向上转型后调用move方法,仍然会调用子类重写后的方法
    Vehicle* myCarAsVehicle = new Car();
    myCarAsVehicle->move(); // 输出: Car is moving on the road

    // 清理资源
    delete myVehicle;
    delete myCar;
    delete myCarAsVehicle;

    return 0;
}

在这个例子中,Car类中的move()方法通过override关键字显式地标记为对Vehicle类中move()方法的重写。如果Car类中的move()方法签名与Vehicle类中的不匹配,编译器将报错,指出override关键字的使用不正确。这有助于在编译时捕获潜在的错误,并提高代码的可读性和可维护性。


3. 使用final说明符

3.1 作用

  1. 阻止虚函数被重写:它明确告诉编译器,该虚函数不能被派生类重写,若重写编译器会报错。

  2. 阻止类被继承:它还可以声明类,若一个类声明了final,则不能作为基类被继承。

3.2 Demo

阻止类被继承

首先,我们定义一个被final修饰的类FinalClass,这意味着FinalClass不能被其他类继承。

#include <iostream>

// 使用final修饰的类,不能被继承
class FinalClass final {
public:
    void show() {
        std::cout << "This is a final class, cannot be inherited." << std::endl;
    }
};

// 尝试继承FinalClass会导致编译错误
// class InheritingClass : public FinalClass { // 编译错误
// };

int main() {
    FinalClass fc;
    fc.show();
    // return 0; // 实际上这里不需要显式返回0,在main函数中隐式返回
}

阻止虚函数被覆盖

接下来,我们定义一个基类Base,其中包含一个虚函数virtualFunc(),并在派生类Derived中尝试覆盖它。然后,我们在Base类中修改virtualFunc()final,以阻止它在任何派生类中被覆盖。

首先,展示正常的虚函数覆盖:

#include <iostream>

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

class Derived : public Base {
public:
    void virtualFunc() override { // 注意这里使用了override关键字,但即使不使用,编译器也会正常覆盖
        std::cout << "Derived class overriding virtual function" << std::endl;
    }
};

int main() {
    Derived d;
    Base* b = &d;
    b->virtualFunc(); // 输出: Derived class overriding virtual function
    return 0;
}

然后,我们修改Base类中的virtualFunc()final,以阻止覆盖:

#include <iostream>

class Base {
public:
    virtual void virtualFunc() final { // 使用final阻止覆盖
        std::cout << "Base class virtual function (final)" << std::endl;
    }
};

class Derived : public Base {
public:
    // void virtualFunc() override { // 编译错误,因为virtualFunc()在Base中已被标记为final
    //     std::cout << "Cannot override final function" << std::endl;
    // }
};

int main() {
    Derived d;
    d.virtualFunc(); // 调用Base类中的virtualFunc(),因为Derived不能覆盖它
    return 0;
}

在这个修改后的例子中,如果尝试在Derived类中覆盖virtualFunc(),编译器将报错,因为virtualFunc()Base类中被标记为final

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用:在1.h 中#include了 2.h ,然后在2.h 中又#include了 1.h ,然后这个错误就出现了 。 引用:使用 CopyOnWriteArrayList 需要注意的“坑”主要有两个方面。一个是应用场景,CopyOnWriteArrayList 仅适用于写操作非常少的场景,而且能够容忍读写的短暂不一致。例如上面的例子中,写入的新元素并不能立刻被遍历到。另一个需要注意的是,CopyOnWriteArrayList 迭代器是只读的,不支持增删改。因为迭代器遍历的仅仅是一个快照,而对快照进行增删改是没有意义的。 。 引用://final,override出现在形参列表以及尾置返回类型之后 #include using namespace std; struct B{ virtual void f1(int) const; virtual void f2(int); void f3(int) final;//出错,final不能修饰非虚函数 }; ...。 引用中的问题是由于在1.h中包含了2.h,在2.h中又包含了1.h,导致循环包含的错误。为了解决这个问题,你可以使用头文件保护符号来防止循环包含。在1.h和2.h的开头分别加上#ifndef 和 #define 防止重复包含,然后在结尾处加上#endif来关闭头文件保护符号。 引用中的问题是关于使用CopyOnWriteArrayList时需要注意的两个方面。首先,CopyOnWriteArrayList适用于写操作非常少的场景,并且可以容忍读写的短暂不一致。也就是说,当你向CopyOnWriteArrayList中写入新元素时,可能不能立刻被遍历到。其次,CopyOnWriteArrayList的迭代器是只读的,不支持增删改操作。因为迭代器遍历的是一个快照,对快照进行增删改是没有意义的。 引用中的问题是关于finaloverride的使用位置的错误。在C++中,finaloverride关键字应该出现在成员函数的声明或定义中,并且要紧跟在函数名之后的括号内。在给定的代码中,final被错误地放在了函数定义的末尾,导致出现错误。要解决这个问题,你需要将final关键字放在函数声明或定义的括号内正确使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值