C++

重载、覆盖、隐藏

Posted by DEVIN on Sun, Jun 18, 2023

C++类层次中的同名函数,有三种关系:

1.重载**(overload)** 概念:相同的范围(同一个类)中的同名函数参数列表不同。 1)与返回值类型没有关系。 2)const是有效的重载。 3)virutal是无效的重载。virtual关键字可有可无,不影响是否是重载函数。

2.重写、覆盖**(override)** 概念:在派生类中覆盖基类中的同名函数,要求 1)基类函数必须是虚函数 2)与基类的虚函数有相同的参数列表 3)与基类的虚函数有相同的返回类型、或者满足赋值兼容规则的指针/引用类型返回值(见下面的例子)。

以下情况不能实现多态:同名函数缺省参数不一致、同名函数用const修饰

3.隐藏**(hide,oversee)** 概念:隐藏指在某些情况下,派生类中的函数屏蔽了基类中的同名函数。这些情况包括两个函数参数相同,但是基类不是虚函数。—(参数不同可以实现重载) 区别:和覆盖的区别在于基类函数是否是虚函数。

可以使用using声明解决基类成员被隐藏的问题,例如:

 1class Base {
 2public:
 3    virtual void f(int) { std::cout << "Base::f\n"; }
 4    void g(char)        { std::cout << "Base::g\n"; }
 5    void h(int)         { std::cout << "Base::h\n"; }
 6protected:
 7    int m;
 8private:
 9    int k;
10};
11
12class Derived : public Base {
13public:
14    using Base::m; // 此时 m 为public
15//    using Base::k; // error报错
16
17    using Base::f;
18    void f(int) { std::cout << "Derived::f\n"; } // D::f(int) 覆盖 B::f(int)
19
20    using Base::g; // 不声明的话,需要通过 obj.Base::g 使用
21    void g(int) { std::cout << "Derived::g\n"; } // g(int) 与 g(char) 均作为派生类的成员可见,实现 重载
22
23    using Base::h;
24    void h(int) { std::cout << "Derived::h\n"; } // D::h(int) 隐藏 B::h(int)
25};
26
27int main()
28{
29    Derived derived;
30    Base &base = derived;
31
32    derived.m = 1;
33
34    base.f(1);      // Derived::f 虚函数多态
35    derived.f(1);   // Derived::f
36
37    derived.g('a'); // Base::g    重载
38    derived.g(1);   // Derived::g 重载
39
40    base.h(1);      // Base::h    基类引用没有实现动态多态
41    derived.h(1);   // Derived::h 隐藏
42}