在 C++ 中,函数隐藏、重载、覆盖(重写)是面向对象编程中容易混淆的概念,它们的核心区别体现在作用范围、函数关系和行为表现上。以下是详细解析:

1. 函数重载(Overload)

定义:在同一作用域内,声明多个函数名相同但参数列表不同的函数(参数类型、个数、顺序不同),编译器会根据实参自动匹配对应的函数。

特点:

必须在同一类内或同一全局 / 命名空间作用域中。

函数名相同,参数列表必须不同(与返回值类型无关)。

不涉及继承关系。

示例:

class A {

public:

    void func(int x) { ... }       // 重载1:参数为int

    void func(double x) { ... }    // 重载2:参数为double(与1重载)

    // void func(int x) const { ... }  // 也是重载(const修饰符不同)

};

2. 函数覆盖(Override,也称 “重写”)

定义:在继承关系中,派生类定义了一个与基类中虚函数完全相同(函数名、参数列表、返回值类型均相同)的函数,从而覆盖基类的虚函数实现。

特点:

必须发生在基类与派生类之间。

基类函数必须用 virtual 声明为虚函数。

派生类函数与基类函数函数名、参数列表、返回值类型完全一致(C++11 允许协变返回类型,即返回值为基类 / 派生类指针 / 引用)。

作用:实现多态,通过基类指针 / 引用调用时,会根据对象实际类型执行派生类的重写函数。

示例:

class Base {

public:

    virtual void func() { ... }  // 基类虚函数

};



class Derived : public Base {

public:

    void func() override { ... }  // 重写基类虚函数(override关键字可选,用于检查正确性)

};

3. 函数隐藏(Hide,也称 “名字隐藏”)

定义:在继承关系中,派生类定义的函数与基类函数同名,但因参数列表不同或基类函数非虚函数,导致基类函数被 “隐藏”(派生类中无法直接访问基类的同名函数)。

特点:

发生在基类与派生类之间,函数名相同但不满足覆盖条件。

隐藏的原因:

基类函数非虚函数,派生类同名函数参数不同(无论是否有 virtual)。

基类函数是虚函数,但派生类同名函数参数不同(此时不构成覆盖,而是隐藏)。

访问被隐藏的基类函数需用 基类名::函数名 显式调用。

示例:

class Base {

public:

    void func(int x) { ... }      // 非虚函数

    virtual void show() { ... }   // 虚函数

};



class Derived : public Base {

public:

    void func(double x) { ... }   // 隐藏Base::func(int)(参数不同)

    void show(int x) { ... }      // 隐藏Base::show()(参数不同,不构成覆盖)

};



// 调用时:

Derived d;

d.func(10);       // 调用Derived::func(double)(Base::func(int)被隐藏)

d.Base::func(10); // 显式调用被隐藏的基类函数

d.show();         // 错误!Base::show()被隐藏,需显式调用 d.Base::show()

关键区别总结:

概念 作用范围 函数关系要求 核心目的 / 效果
重载 同一作用域 同名,参数不同(与返回值无关) 简化同名功能的调用(编译期绑定)
覆盖(重写) 基类与派生类 同名、同参数、同返回值,基类为虚函数 实现多态(运行期绑定)
隐藏 基类与派生类 同名,不满足覆盖条件 派生类同名函数屏蔽基类函数

注意:

override 关键字(C++11)可显式声明派生类函数是重写基类虚函数,编译器会检查是否满足覆盖条件,避免误写为隐藏。

隐藏可能导致意外行为,使用时需注意派生类与基类同名函数的参数匹配。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐