C++之重载、覆盖和隐藏

C++之重载、覆盖和隐藏

转自:http://www.cnblogs.com/jingliming/p/4432342.html

C++的虚函数体现了面向对象编程的多态性这一特征,但是在派生类继承的过程中,由于覆盖往往会使基类的某些函数不能够被调用,这里我们就重载(overload)、覆盖(override)、隐藏(hide)进行简单的讨论和总结。

一、重载

  在同一可访问区内被声名的几个具有不同参数列的(参数的类型、个数、顺序不同)同名函数,程序会根据不同的参数列来确定具体调用哪个函数,这种机制叫重载,重载不关心函数的返回值类型。

1 void overload();
2 void overload(int);
3 void overload(int, int);
4 void overload(double,int);
5 void overload(double);

上例均为overload函数的重载函数,

重载的特点主要有

1) 相同的范围(在同一个类中);
2) 函数名字相同;
3) 参数不同;
4) virtual关键字可有可无。

二、覆盖

  指派生类中存在重新定义的函数,其函数名、参数列、返回值类型必须同父类中的相对应被覆盖的函数严格一致,覆盖函数和被覆盖函数只有函数体(花括号中的部分)不同,当派生类对象调用子类中该同名函数时会自动调用子类中的覆盖版本,而不是父类中的被覆盖函数版本,这种机制就叫做覆盖。(由虚函数引起的)

复制代码
 1 class Base
 2 {
 3 public:
 4     virtual void override();
 5     virtual void override(int);
 6 
 7 };
 8 class Device :public Base
 9 {
10 public:
11     void override();
12 };
复制代码
1     Device d;
2     int a = 0;
3     d.override();  //OK
4     d.override(a); //错误,基类的函数被派生类覆盖,因此不能调用基类定义的函数

覆盖的主要特点有

1) 不同的范围(分别位于派生类与基类);
2) 函数名字相同;
3) 参数相同;
4) 基类函数必须有virtual关键字。

三、隐藏

指派生类的函数屏蔽了与其同名的基类函数,其特征如下
1) 如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。
2) 如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。

复制代码
 1 #include <iostream.h>
 2 
 3 class Base
 4 
 5 {
 6 
 7 public:
 8 
 9 virtual void f(float x){ cout << "Base::f(float) " << x << endl; }
10 
11 void g(float x){ cout << "Base::g(float) " << x << endl; }
12 
13 void h(float x){ cout << "Base::h(float) " << x << endl; }
14 
15 };
16 
17 class Derived : public Base
18 
19 {
20 
21 public:
22 
23 virtual void f(float x){ cout << "Derived::f(float) " << x << endl; }
24 
25 void g(int x){ cout << "Derived::g(int) " << x << endl; }
26 
27 void h(float x){ cout << "Derived::h(float) " << x << endl; }
28 
29 };
复制代码

复制代码
 1 void main(void)
 2 
 3 {
 4 
 5 Derived d;
 6 
 7 Base *pb = &d;
 8 
 9 Derived *pd = &d;
10 
11 // Good : behavior depends solely on type of the object
12 
13 pb->f(3.14f); //运行结果: Derived::f(float) 3.14 
14 
15 pd->f(3.14f); //运行结果: Derived::f(float) 3.14
16 
17 // Bad : behavior depends on type of the pointer
18 
19 pb->g(3.14f); //运行结果: Base::g(float) 3.14 
20 
21 pd->g(3.14f); //运行结果: Derived::g(int) 3 
22 
23 // Bad : behavior depends on type of the pointer
24 
25 pb->h(3.14f); //运行结果: Base::h(float) 3.14 
26 
27 pd->h(3.14f); //运行结果: Derived::h(float) 3.14 
28 
29 }
复制代码
注意:f()函数属于覆盖,而g()与h()属于隐藏。从上面的运行结果,我们可以注意到在覆盖中,用基类指针和派生类指针调用函数f()时,系统都是执行的派生类函数f(),而非基类的f(),这样实际上就是完成的“接口”功能。而在隐藏方式中,用基类指针和派生类指针调用函数f()时,系统会进行区分,基类指针调用时,系统执行基类的f(),而派生类指针调用时,系统“隐藏”了基类的f(),执行派生类的f(),这也就是“隐藏”的由来。

 
 

 
no pains ,no gains. 给自己加油,为未来奋斗。
posted @ 2016-10-08 09:37  flylong0204  阅读(156)  评论(0)    收藏  举报