注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

逍遥子 曰:

得失失得 何必患得患失 舍得得舍 不妨不舍不得

 
 
 

日志

 
 

[原] 函数的重载、覆盖和隐藏  

2013-06-07 23:11:36|  分类: C/C++ |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

从下面的这个例子中可以看到函数的重载、覆盖和隐藏的具体意思,以及它们之间的区别:


#include<iostream>

using namespace std;


class CParent
{
public:
int Add(int iVal) // [P-1] 
{
cout<<"in function [<--CParent--> int Add(int iVal)]"<<endl;
return iVal+1;
}


int Add(char c)//[P-2] 
{
cout<<"in function [<--CParent--> int CParent::Add(char c)]"<<endl;
return 10;
}

int Div(float fVal) //[P-3]
{
cout<<"in function [<--CParent--> int Div(float fVal)]"<<endl;
return fVal/10;
}


virtual int TestVtl(int iVal) //[P-4]
{
cout<<"in function [<--CParent--> virtual int TestVtl(int iVal)]"<<endl;
return iVal;
}


virtual void TestVtl2(int iVal)
{
cout<<"in function [<--CParent--> virtual voidTestVtl2(int iVal)]"<<endl;
}


}


class CChild: public CParent
{
public:
int Add(int iVal) // [C-1]
{
cout<<"in function [<--CChild--> int Add(int iVal)]"<<endl;
return iVal+100;
}



bool Div(bool bVal) //[C-2]
{
cout<<"in function [<--CChild--> bool Div(bool bVal) ]"<<endl;
return true;
}


int TestVtl(int iVal) //[C-3]
{
cout<<"in function [<--CChild--> virtual int TestVtl(int iVal)]"<<endl;
return iVal;
}


void TestVtl2()
{
cout<<"in function [<--CChild--> virtual void TestVtl2()]"<<endl;
}

}


int main()
{
CParent* pParent = new CChild();
CChild* pChild = (CChild*)pParent;
cout<<"------------------------use pointer: pParent-----------------"<<endl
pParent->Add(10);//与下一句的调用形成重载
pParent->Add('c');
pParent->Div(10);//使用基类的指针就调用基类的函数
pParent->TestVtl(10);//加了virtual关键字,使用基类指针依然可以调用派生类的函数
pParent->TestVtl2(10);


cout<<endl<<"------------------------use pointer: pChild -----------------"<<endl
pChild->Add(10);
pChild->div(10);//覆盖掉基类的同名函数
pChild->TestVtl(10);
pParent->TestVtl2();

delete pParent;
system("pause");


return 0;
}




输出结果:
------------------------use pointer: pParent-----------------
in function [<--CParent--> int Add(int iVal)]
in function [<--CParent--> int CParent::Add(char c)]
in function [<--CParent--> int Div(float fVal)]
in function [<--CChild--> virtual int TestVtl(int iVal)]
in function [<--CParent--> virtual voidTestVtl2(int iVal)]


------------------------use pointer: pChild -----------------
in function [<--CChild--> int Add(int iVal)]
in function [<--CChild--> bool Div(bool bVal) ]
in function [<--CChild--> virtual int TestVtl(int iVal)]
in function [<--CChild--> virtual void TestVtl2()]




函数的重载:
1、是指在同一类中,具有相同的函数名称,但是参数列表不一样,满足上述三个条件即构成重载。
2、重载机制主要用于调用的时候可以根据不同的参数调用不同的函数,它就优点就是方便开发,可以用同一个函数名字定义多个不同的函数功能体,在使用的时候,我们不用制定,编译器会自动帮我们找到正确对应的那个函数。
3、重载机制与关键字virtual没有关系,因为重载是指同一个类中的同名不同参的函数。
4、例如类CParent中的[P-1]和[P-2]两个Add函数的参数列表形成了函数的重载,可以看到 在main函数中使用:pParent->Add(10)和pParent->Add('c')就分别调用了基类的[P-1]和[P-2]这 两个不同的Add函数


函数的覆盖:
1、在具有继承关系的父子类中的函数,它们的名字、参数列表、返回值都完全一样(满足这三者一样的函数的内部签名是一样的),同时基类还有关键字virtual修饰,同时满足上面三个条件,父类就会把基类的函数给覆盖掉。
2、此时可以使用基类的指针访问派生类的函数,例如上面例子中的TestVtl函数,可以察看输出结果在使用基类指针调用TestVtl的时候 pParent->TestVtl(10),输出结果却是:in function [<--CChild--> virtual int TestVtl(int iVal)]
3、覆盖发生在父子类的同名虚函数之间,是基于虚函数表来完成的。


函数的隐藏:
1、在具有继承关系的父子类中,如果父子类中存在同样名字的函数,但是函数的参数列表不一样,则子类就会隐藏掉父类的那个同样名字的函数,隐藏与两点相关:[1] 隐藏与被隐藏的函数分别存在父子类中;[2] 函数名字一样。
2、例如:CParent的Div和CChild类中的Div除了名字一样之外,参数列表和返回值都不一样。
3、如果派生类和基类的函数名字一样,基类中也带关键字virtual,但是参数列表不一样,此时派生类将会隐藏基类的那个同名函数,此时无法引起覆盖, 因为参数不同的函数,其内部的实际签名是不一样的,例如上面例子中的TestVtl2,这个函数在基类中和派生类中都有定义,基类也都有关键字 virtual,但是这里的基类调用的是基类的派生类调用的是派生类的,没有形成重载。




可以看到:
1、重载发生在同一函数中,覆盖和隐藏发生在具有派生关系的父子两个类中。
2、覆盖要求比较严格:函数名字、参数列表、返回值都相同,而且基类还需有Virtual修饰(这样才能将virtual修饰的函数放入虚函数表中)
3、覆盖是基于虚函水表机制来完成的,但是隐藏与虚函数表没有关系。
4、假如父子类中都存在一个
  评论这张
 
阅读(464)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018