c++重载、覆盖、隐藏

重载 overload )是指函数不同的参数列表,对同名函数的名称做修饰,然后这些同名函数就成了不同的函数。在同一可访问域内(注意同一访问域,基类和派生类不属于同一访问域)被声明的几个具有不同参数列表(参数类型、个数、顺序)的同名函数,程序会根据不同的参数列来确定具体调用哪个函数。对于重载函数的调用,在编译期间就已经确定,是静态的,它们的地址在编译期间就绑定好了,与多态无关。注意,重载不关心函数的返回值类型。 
    成员函数被重载的特征: 
    (1)  相同的范围(在同一个类中
    (2)函数名字相同 
    (3)参数不同 
    (4)virtual关键字可有可无 
    
    覆盖 override )是指派生类中存在重新定义基类的函数,其函数名/参数列/返回值类型必须同基类中对应被覆盖的函数严格一致,覆盖函数和被覆盖函数只有函数体不同。当子类重新定义了父类的虚函数后,父类指针会进行动态绑定。 
    覆盖的特征如下: 
    (1)不同的范围( 分别位于基类和派生类中 ) 
    (2)函数名、参数列、返回值严格一致 
    (3)基类函数必须有virtual关键字 

    隐藏 hide )是指派生类的函数屏蔽了与其同名的基类函数,规则如下: 
    (1)如果派生类函数与基类函数同名但是参数不同,则无论有无virtual关键字,基类函数都将被隐藏 
    (2)如果派生类函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字,此时基类的函数被隐藏 
    注:在不同域中,编译器只看函数名,不看其它东西 

关于隐藏和重载有一个很好的例子: 
class A{
public:
    void f(int i){cout << "A" << endl;}
};
class B{
public:
    void f(int i){cout << "B" << endl;}
};
class C : public A, public B{
public:
    void f(char *s){cout << "C" << endl;}
};
int main(void)
{
    C c;
    c.f(2);//如果c++不进行覆盖的化,编译器没法确定调用的是A::f()还是B::f()。
//这不在同一个域中,所以跟重载没有半点关系。
     return 0;
}
如果硬是希望在C中进行重载A的成员函数的化,可以这么设计:
class C : public A, public B { 
public: 
    using A::f; 
    void f(char* s) {cout << "C" << endl;} 
};

注:JAVA中就没有隐藏这种说法,举个例子

class CB {
    public  void f(){
       System.out.println("CB::f()");    
    }
}
 
class CD extends CB {
    public  void f(int a){
       System.out.println("CD::f(int)");
    }
}
 
public class MyTest {
    public static void main(String args[])
    {
       System.out.println("helloWorld");
       CD test = new CD();
       test.f();
       test.f(1);
    }
}

运行结果就是:

helloWorld

CB::f()

CD::f(int)

形象一点就是这个JavaC++就有区别了,感觉Java的比较合常理啊,我爸爸有辆大奔,我自己有辆宝马,我爸爸说,我的大奔就是你的大奔,那我当然既能开大奔,又能开宝马了,凭什么只能开宝马呢?

另外JAVA中private函数不能重载 ,比如:

class CB {
     private  void f(){
       System.out.println("CB::f()");    
    }
    public  void ff(){
       f();
    }
}
 
class CD extends CB {
    public  void f(){
       System.out.println("CD::f()");
    }
}
 
public class MyTest {
   
    public static void main(String args[])
    {
       System.out.println("helloWorld");
       CD cd = new CD();
       CB cb = new CB();
       CB cbd = new CD();
       cd.ff();
       cb.ff();
       cbd.ff();
    }
 
}


运行结果:

helloWorld

CB::f()

CB::f()

CB::f()

而在c++中,直接重载了!

class CB {
 
private:
     virtual void f(){
       cout<< "CB::f()" << endl;
    }
public:
    void ff(){
       f();
    }
};
 
class CD : public CB {
 
private:
    void f(){
       cout<< "CD::f()" << endl;
    }
};
 
int _tmain(int argc, _TCHAR* argv[])
{
    CD test;
    CB test2;
    CB * cb  = &test2;
    CD * cd = &test;
    CB * cbd = &test;
    cb->ff();
    cd->ff();
    cbd->ff();
    return 0;
}


运行结果:

CB::f()

CD::f()

CD::f()

不过说实在的,我觉得没必要这么转牛角尖,为啥要覆盖私有成员函数呢?派生类应该根本见不到基类的私有成员接口,否则破坏了封装性
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值