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 作用
-
阻止虚函数被重写:它明确告诉编译器,该虚函数不能被派生类重写,若重写编译器会报错。
-
阻止类被继承:它还可以声明类,若一个类声明了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
。