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}