override 关键字的作用
override
关键字的作用
1. override
是什么?
override
是 C++11 引入的关键字,用于显式声明一个函数是基类中的虚函数(virtual
)的重写。
它用于 派生类(子类),确认该函数是对 基类(父类)方法的覆盖,增强了代码的可读性和安全性。
2. 为什么要使用 override
?
在 C++ 继承(Inheritance
)机制中,派生类(子类)可以 重写(Override) 基类的 虚函数(Virtual Function)。
但如果函数签名(返回值、参数列表)不匹配,可能导致隐藏(Hiding)错误,而不是正确的覆盖。
📌 使用 override
的两个好处:
- 编译器检查
- 确保重写的是基类中的 虚函数,避免拼写错误或函数签名不匹配的问题。
- 提高可读性
- 明确告诉读者 这个函数是重写基类方法,不是定义一个新方法。
3. override
的使用方式
✅ 正确的用法
class Base {
public:
virtual void show() { // 基类中的虚函数
std::cout << "Base class show()" << std::endl;
}
};
class Derived : public Base {
public:
void show() override { // 正确:显式重写基类的虚函数
std::cout << "Derived class show()" << std::endl;
}
};
🔹 如果 Base
中的 show()
不是 virtual
,那么 Derived
只是隐藏了它,而不是重写。
🔹 使用 override
让代码更加清晰,避免隐式的函数覆盖问题。
4. override
发现隐藏错误
❌ 错误示例(未正确覆盖基类方法)
class Base {
public:
virtual void show(int x) { // 虚函数带参数
std::cout << "Base class show(int)" << std::endl;
}
};
class Derived : public Base {
public:
void show() override { // ❌ 错误:基类没有 show(),只有 show(int)
std::cout << "Derived class show()" << std::endl;
}
};
🔸 🔴 编译会报错:
error: 'show' marked 'override' but does not override any member functions
✅ 正确做法:
class Derived : public Base {
public:
void show(int x) override { // ✅ 正确匹配基类的 `show(int)`
std::cout << "Derived class show(int)" << std::endl;
}
};
🚀 因为 override
关键字强制要求基类中必须存在同样的方法接口,避免了隐藏错误!
5. override
结合 final
使用
如果不希望派生类继续重写该函数,可以使用 final
关键字:
class Base {
public:
virtual void show() final { // `final` 表示不能再被子类重写
std::cout << "Base class show()" << std::endl;
}
};
class Derived : public Base {
public:
void show() override { // ❌ 编译错误:不能重写 final 方法
std::cout << "Derived class show()" << std::endl;
}
};
🔴 编译错误:
error: virtual function ‘virtual void Derived::show()’ overriding final function
6. override
在 ROS2 和 rclcpp_lifecycle
中的作用
在 ROS2 控制器 rclcpp_lifecycle::LifecycleNodeInterface
里,我们通常需要重写 LifecycleNode
的生命周期回调函数。例如:
#include <rclcpp/rclcpp.hpp>
#include <rclcpp_lifecycle/lifecycle_node.hpp>
class MyLifecycleNode : public rclcpp_lifecycle::LifecycleNode {
public:
explicit MyLifecycleNode(const std::string & node_name)
: LifecycleNode(node_name) {}
// `on_configure()` - 进入 Inactive 状态时执行
rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn
on_configure(const rclcpp_lifecycle::State &) override {
RCLCPP_INFO(get_logger(), "节点已配置");
return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
}
// `on_activate()` - 进入 Active 状态时执行
rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn
on_activate(const rclcpp_lifecycle::State &) override {
RCLCPP_INFO(get_logger(), "节点已激活");
return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
}
// `on_deactivate()` - 进入 Inactive 状态时执行
rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn
on_deactivate(const rclcpp_lifecycle::State &) override {
RCLCPP_INFO(get_logger(), "节点已停用");
return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
}
};
👉 在 ROS2 中,为了确保 LifecycleNode
正确覆盖基类的方法,必须使用 override
。
❌ 如果函数签名有误,比如 on_activate(int arg)
,编译器会报错,确保不会出现隐藏错误。
7. 总结
✅ override
用于 显式声明派生类中的函数是基类虚函数的重写。
✅ 好处:
- 防止拼写错误
- 避免隐藏错误
- 提高可读性
✅ 在 C++ 继承(OOP) 和 ROS2LifecycleNode
生命周期管理 中经常使用。
✅ 结合final
可以防止继续被派生类重写。
🚀 override
是 C++ 现代开发的重要特性,建议在所有重写 virtual
方法时都使用! 🚀