加载中…
个人资料
一叶知秋
一叶知秋
  • 博客等级:
  • 博客积分:0
  • 博客访问:425,024
  • 关注人气:82
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
谁看过这篇博文
加载中…
正文 字体大小:

C++中覆盖,隐藏,多态等混淆概念梳理程序示例

(2013-04-10 20:56:50)
标签:

覆盖

隐藏

it

分类: C
#include   
using namespace std;  
class A 
    public:   
    virtual void f() //被覆盖 函数相同,参数相同,含有virtual关键字  多态
    {    
        cout<<"A::f()"<<endl;  
    }   
    void f()const  
    {    
        cout<<"A::f()Const"<<endl;  
   
    void foo()//会被隐藏 函数相同,参数相同,没有virtual关键字
    {
        cout<<"A::foo()"<<endl;
    }
    void fun(int i)//会被隐藏 函数相同,参数不同
    {
        cout<<"A::fun()"<<endl;
    }
    virtual void fun1(int i)//会被隐藏 函数相同,参数不同 虚函数
    {
        cout<<"A::fun1()"<<endl;
    }

};   
class B:public A 
{  
    public:   
    virtual void f() //覆盖基类函数
    {    
        cout<<"B::f()"<<endl;  
    }   
    void f()const  
    {    
        cout<<"B::f()Const"<<endl;  
   
    void foo()//隐藏基类函数 
    {
        cout<<"B::foo()"<<endl;
    }
    void fun(float i , int j)//隐藏基类函数 函数相同,参数不同 非虚
    {
        cout<<"B::fun()"<<endl;
    }
    virtual void fun1(float i,int j)//隐藏基类函数 函数相同,参数不同 虚函数(这里相对B的子类                                           来说,才能实现多态)
   
       cout<<"B::fun1()"<<endl;
    }

};   
void g(const A *a) 
{   
    a->f(); 
}   
int main() 
{   

    A * a= new B();  
    a->f();  //此处是覆盖,函数名相同,参数相同,virtual函数 实现的是多态,调用的是派生类的虚                    函数
    g(a);   //此处,参数是指向基类的const指针,所以调用的是基类中的const非虚函数
    a->foo();//a是指向基类的指针,对于非虚函数,须根据指针的原始类型而定。

    a->fun(3.14f, 7); 出错,因为基类对象中没有实现该函数,不能调用B类中的同名函数
    a->fun(2);//a是指向基类的指针,对于非虚函数,须根据指针的原始类型而定

    a->fun1(3.1f, 7); 出错,因为a只能调用基类中的函数,基类中的fun1(float int)不是对基类函数                             的重新定义,所以不能动态调用
    a->fun1(1);//a是指向基类的指针,对于非虚函数,须根据指针的原始类型而定

    B * b = new B;

    b->foo();//隐藏了基类函数 函数相同,参数相同,没有virtual关键字
    b->fun(3.14f, 7);
    b->A::fun(2);//隐藏了基类函数 函数相同,参数不同 非虚函数  必须显式调用
    b->fun1(3.1f, 7);
    b->A::fun1(1);//隐藏了基类函数 函数相同,参数不同 虚函数  必须显式调用
    system("pause");   

    return 0; 
}  

总结:覆盖:基类和派生类中的函数名相同,参数也相同,而且基类中是虚函数。此时为覆盖。
      如果用一个“基类之指针”指向一个“派生类之对象”,那么,对于覆盖的情况,调用的是派生类中的函数。如上文的main中第二行。
      当然,如果不是覆盖的情况,那么就是视指针的原始类型而定要调用哪一个函数。因为,对于一般的情况,除了多态外,一个基类之指针指向一个派生类指对象,那么经由该指针,只能调用该基类索定义的成员。如果是虚函数(覆盖情况),则视实际所指对象的类型而定。

除了覆盖外,还有一种是隐藏的情况:
1,如果派生类的函数和基类的函数同名,但是参数不同,无论此时是否是虚函数,基类的函数被隐藏。
2,如果派生类的函数和基类的函数同名,且参数相同,但是基类没有virtual ,此时基类函数被隐藏。

注意:此处需要将隐藏和覆盖区分开,隐藏的情况不能实现动态绑定,即使基类是virtual函数。这种情况下,指向基类的指针引用派生类的对象,指针还是只能调用基类中的函数,调用派生类中的同名函数,会报错。

虚函数就是允许被其子类重新定义的成员函数。
覆盖(OVERRIDE):子类重新定义父类虚函数的做法,或者叫重写。
重载(OVERLOAD):是指允许存在多个函数名称相同的函数,但是这些函数的参数表不同;注意:重载函数的调用是在编译期间,是属于静态的,所以它与多态无关!! 真正与多态相关的是覆盖/重写!

当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态地调用子类的函数,这样的函数调用是在编译期间无法确定的(调用的子类的虚函数的地址无法给出)。因此,这样的函数地址是在运行期间绑定的(动态绑定)。


0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4000520066 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有