重载 覆盖 隐藏

【1】重载

(1)重载是指在同一个类内被声明的几个具有不同参数列的同名函数。

函数名必须相同,不考虑函数的返回值类型。

(2)示例代码如下:

 1 #include <iostream>
 2 using  namespace std;
 3 
 4 class Sample
 5 {
 6 public:
 7     void  Func(int a, char ch)       // 原函数
 8     {
 9         cout << "a " << a << "  " << "ch " << ch << endl;
10     }
11     void  Func(char ch, int a)   // 重载1:参数顺序不同
12     {
13         cout << "ch " << ch << " " << "a " << a << endl;
14     }
15     void  Func(int a)           // 重载2:参数个数不同
16     {
17         cout << "a  " << a << endl;    
18     }
19     void  Func(int a, double db) // 重载3:参数类型不同
20     {
21         cout << "a " << a << " " << "db " << db << endl;
22     }
23     void  Func(int a, char ch) const      // 重载4:常函数(被const修饰的函数)
24     {
25         cout << "a " << a << "  " << "ch " << ch << endl;
26     }
27     /*
28     int Func(int a, char ch)      // error! 非重载,编译无法通过。因为编译器认为是重定义。
29     {
30         cout << "a" << a << "  " << "ch" << endl;
31         return a;
32     }
33     */
34 };
35 
36 void main()
37 {
38     Sample ss;
39     ss.Func(10, 'a');
40     ss.Func('a', 20);
41     ss.Func(30);
42     ss.Func(40, 12.34);
43     system("pause");
44 }
45 
46 // 运行结果:
47 /*
48 a 10  ch a
49 ch a a 20
50 a  30
51 a 40 db 12.34
52 请按任意键继续. . .
53 */

分析总结:

<1> 在同一个类中(同一作用域中)。

<2> 方法名相同。

<3> 参数个数、参数类型或者参数顺序不同。

<4> 与函数的返回值类型无关。

如果仅仅返回值类型不同,那么对编译器来说会在调用时产生二义性。

所以,抛开返回值类型再分析即相当于重定义,重定义是被禁止的(一个函数只允许有一份函数体)。

<5> const修饰。类中成员函数,const 用在函数后一般修饰的是this指针。所以,也算重载的范畴。

【2】覆盖

(1)覆盖也叫重写,是指在派生类中重写基类某虚函数的实现体的一种形式。

函数名、参数列表、返回值类型都必须同基类被重写的虚函数的严格一致。

仅仅只是函数实现体不同。即达到严格的覆盖目的。

(2)示例代码如下:

 1 #include <iostream>
 2 using  namespace std;
 3 
 4 class Sample
 5 {
 6 public:
 7     virtual void Func()
 8     {
 9         cout << "Sample::Func" << endl;
10     }
11 };
12 
13 class  Test : public Sample
14 {
15 public:
16     void Func()
17     {
18         cout << "Test::Func" << endl;
19     }
20 };
21 
22 void  main()
23 {
24      Sample* pa = new Test();
25      pa->Func();
26      delete pa;
27      pa = NULL;
28      system("pause");
29 }
30 /* run out:
31 Test::Func
32 请按任意键继续. . .
33 */

分析总结:

<1> 不同的范围(分别位于基类和派生类,不同作用域中)。

<2> 方法名相同。

<3> 参数严格一致。

<4> 返回类型相同。

<5> 基类函数前必须要加关键字virtual,即必须是虚函数。

【3】隐藏

(1)隐藏是指在派生类中隐藏基类的同名函数。

与重载范围不同,隐藏函数和被隐藏函数不在同一个类中。

与覆盖条件不同,隐藏函数和被隐藏函数的参数可以相同,也可以不同,但是函数名必须要相同。

重要备注

<1> 当参数相同时,如果基类中的函数被virtual修饰,基类的函数就是所谓被覆盖。

<2> 当参数相同时,如果基类中的函数没有被virtual修饰,基类的函数就是所谓被隐藏。

<3> 当参数不相同时,无论基类中的函数是否被virtua修饰,基类的函数都是所谓的被隐藏。

(2)示例代码如下:

  1 #include <iostream>
  2 using namespace std;
  3 
  4 class Sample
  5 {
  6 public:
  7     virtual void Func0()
  8     {
  9         cout << "Sample::Func0" << endl;
 10     }
 11 
 12     virtual void Func1()
 13     {
 14         cout << "Sample::Func1" << endl;
 15     }
 16 
 17     void Func2(int a)
 18     {
 19         cout << "Sample::Func2" << endl;
 20     }
 21 
 22     void Func3(const char *db)
 23     {
 24         cout << "Sample::Func3" << endl;
 25     }
 26 
 27     void Func4(int n, int m)
 28     {
 29         cout << "Sample::Func4" << endl;
 30     }
 31 };
 32 
 33 class Test : public Sample
 34 {
 35 public:
 36     // 覆盖
 37     void Func0()  // 带virtual关键字,参数相同
 38     {
 39         cout << "Test::Func0" << endl;
 40     }
 41     // 隐藏1
 42     void Func1(int a)   // 带virtual关键字,参数不同
 43     {
 44         cout << "Test::Func1" << endl;
 45     }
 46 
 47 #if 0
 48     int Func1()   // 带virtual关键字,参数相同,但返回值不同
 49     {
 50         cout << "Test::Func1_R" << endl;
 51         return 0;
 52     }
 53     // -- E0317    返回类型与重写虚拟函数 "Sample::Func1" 的返回类型 "void" 既不相同,也不协变
 54 #endif
 55 
 56     // 隐藏2
 57     void Func2(int a)   // 不带virtual,参数相同,返回值相同
 58     {
 59         cout << "Test::Func2" << endl;
 60     }
 61 
 62 #if 0
 63     int Func2(int a)   // 不带virtual,参数相同,但返回值不同
 64     {
 65         cout << "Test::Func2_R" << endl;
 66         return 0;
 67     }
 68     // -- E0311    无法重载仅按返回类型区分的函数
 69 #endif
 70 
 71     // 隐藏3
 72     void Func3(int a)   // 不带virtual,参数不同,返回值相同
 73     {
 74         cout << "Test::Func3" << endl;
 75     }
 76     // 隐藏4
 77     int Func4(double dn, double dm) // 不带virtual,参数不同, 返回值不同
 78     {
 79         cout << "Test::Func4" << endl;
 80         return 0;
 81     }
 82 };
 83 
 84 int main()
 85 {
 86     Test t1;
 87     t1.Func0();  // Test::Func0 
 88 //  t1.Func1();  // error! 被隐藏,无法调用
 89     t1.Func1(10); // Test::Func1
 90     t1.Func2(20); // Test::Func2
 91 
 92     const char *str = "kaizen";
 93 //  t1.Func3(str);  // error! 被隐藏,无法调用
 94     t1.Func3(30);   // Test::Func3
 95     t1.Func4(10, 20); // Test::Func4
 96     cout << endl;
 97 
 98     Sample* pSamp = new Test();
 99     pSamp->Func0(); // Test::Func0
100     pSamp->Func1(); // Sample::Func1
101     pSamp->Func2(200); // Sample::Func2
102     pSamp->Func3(str); // Sample::Func3
103     pSamp->Func4(100, 200); // Sample::Func4
104     delete pSamp;
105     pSamp = NULL;
106     cout << endl;
107 
108     Test* pTest = new Test();
109     pTest->Func0(); // Test::Func0
110 //  pTest->Func1();  // error! 参数不匹配
111     pTest->Func2(200); // Test::Func2
112 //  pTest->Func3(str);  // error! 参数不匹配
113     pTest->Func4(100, 200); // Test::Func4
114     delete pTest;
115     pTest = NULL;
116 
117     system("pause");
118 
119     return 0;
120 }
121 // run out:
122 /*
123 Test::Func0
124 Test::Func1
125 Test::Func2
126 Test::Func3
127 Test::Func4
128 
129 Test::Func0
130 Sample::Func1
131 Sample::Func2
132 Sample::Func3
133 Sample::Func4
134 
135 Test::Func0
136 Test::Func2
137 Test::Func4
138 请按任意键继续. . .
139 */

分析总结:

<1> 不同的范围(分别位于基类和派生类,不同作用域)。

<2> 方法名相同。

<3> 有关键字virtual,必须要参数不同。

<4> 无关键字virtual,参数任意。

<5> 图解

【4】总结

三者的关系,总结为一张图:

Good Good Study, Day Day Up.

顺序 选择 循环 总结

作者:kaizen
声明:本文版权归作者和博客园共有,欢迎转载。但未经作者同意必须保留此声明,且在文章明显位置给出本文链接,否则保留追究法律责任的权利。
签名:顺序 选择 循环
原文地址:https://www.cnblogs.com/Braveliu/p/2843255.html