一、理论
- 重载(Overload)
同一个作用域内,函数名相同,参数列表不同(参数个数、类型、顺序)。
返回值不能单独作为重载区分依据
属于编译期决议(静态绑定)
- 重写 / 覆盖(Override)
发生在继承关系,基类虚函数,子类重新实现。
函数名、参数列表、返回值必须匹配(协变返回除外)
基类函数必须加 virtual
运行期决议(动态绑定,多态核心)
- 重定义(隐藏,Redefine / Hide)
继承关系中,子类写了和基类同名函数,不是虚函数,直接把基类同名函数隐藏。
参数列表可以相同/不同
没有virtual,不触发多态
静态绑定:用基类指针调用,依然执行基类函数;子类指针调用执行子类函数
一句话速记
重载:同一类/同一作用域,同名不同参
重写:继承 + virtual,子类覆盖虚函数,实现多态
重定义:继承,同名但不是虚函数,隐藏基类函数
二、代码示例
#include <iostream>
// 影像算法基类
class BaseAlg {
public:
// 【重载】同一作用域,同名,参数不同
void setParam(int exp) {
std::cout << "base setParam int exp\n";
}
void setParam(float ratio) {
std::cout << "base setParam float ratio\n";
}
// 虚函数,用于【重写】
virtual void runFrame() {
std::cout << "base alg process frame\n";
}
// 普通成员函数,用于【重定义(隐藏)】
void getVersion() {
std::cout << "base version 1.0\n";
}
};
class NRAlg : public BaseAlg {
public:
// 【重写override】基类virtual函数,子类重新实现
void runFrame() override {
std::cout << "NR denoise process frame\n";
}
// 【重定义/隐藏】和基类同名,无virtual,隐藏基类getVersion
void getVersion() {
std::cout << "NR alg version 2.0\n";
}
};
int main()
{
BaseAlg* alg = new NRAlg();
alg->runFrame(); // ✅重写,动态绑定,调用NRAlg::runFrame
alg->getVersion(); // ❗重定义,不是多态,调用BaseAlg::getVersion
BaseAlg obj;
obj.setParam(1000);
obj.setParam(1.2f); // 重载,编译期匹配参数类型
delete alg;
return 0;
}
三、手机影像算法集成实际工作场景
影像管线多算法插件(降噪、HDR、锐化),面向对象封装,经常用到这套继承体系:
重载 Overload
封装算法参数接口,setParam 重载:支持传入int曝光值、float增益、结构体AE参数。
对外接口封装,同一函数名,不同参数,上层HAL调用更友好。
注意:extern "C"导出接口不能用重载,前面讲过,C不支持重载。
重写(Override)
写统一算法插件基类 ImagePlugin,基类定义虚函数 processFrame()。
降噪、HDR、锐化各个算法子类override重写processFrame。
Camera HAL上层统一用基类指针管理所有算法插件,调用processFrame,自动执行对应算法的帧处理逻辑,这就是多态。
工程规范:C++11后建议加上override关键字,编译器校验,防止写错函数签名,导致本该重写变成重定义。
重定义(隐藏)------ 高频坑!
忘记写virtual,子类写同名函数,以为实现多态,结果只是隐藏。
用基类指针调用,永远跑基类函数,算法逻辑不生效,预览画面没有降噪效果,很难排查。
面试坑:很多人把重定义当成重写,这是典型错误。
工程避坑
需要多态:基类函数加virtual,子类加override
仅同作用域多个同名接口:使用重载
继承场景不要无意写出重定义,避免预期之外的函数隐藏
✅ 精简版
重载发生在同一个作用域,函数名相同,参数列表不同,编译期静态绑定。
重写(覆盖)发生在继承体系,基类是virtual虚函数,子类实现相同签名函数,运行时动态绑定,实现多态,推荐加override关键字校验。
重定义又叫隐藏,继承中子类写同名函数,没有virtual,不会触发多态,基类指针调用仍然执行基类函数。
在影像插件开发中,我们用重写实现统一算法基类的多态,不同算法实现各自processFrame;重载用于封装不同类型参数的setParam接口;要警惕无意的重定义,造成算法函数没有按预期执行。