重载,重定义,重写(覆盖),名字隐藏

主要有三种关系:重载(overload),覆盖(重写)(override),隐藏(重定义)(hide,oversee)
一、重载(overload)-水平关系
指函数名相同,但是它的参数表列个数或顺序,类型不同。但是不能靠返回类型来判断。
(1)相同的范围(在同一个类中) ;
(2)函数名字相同;
(3)参数列表不同;
(4)virtual 关键字可有可无。
(5)返回值可以不同;

二、重写(也称为覆盖 override)-垂直关系
是指派生类重新定义基类的同名虚函数,特征是:
(1)不在同一个作用域(分别位于派生类与基类) ;
(2)基类函数必须有 virtual 关键字,不能有 static 。
(3)与基类虚函数参数类型相同;
(4)与基类虚函数参数个数相同;
(5)与基类虚函数返回值相同(或是协变),否则报错;<—-协变这个概念我也是第一次才知道…

(6)重写函数的访问修饰符可以不同。尽管 virtual 是 private 的,派生类中重写改写为 public,protected 也是可以的

三、重定义(也成隐藏)
(1)不在同一个作用域(分别位于派生类与基类) ;
(2)函数名字相同;
(3)返回值可以不同;
(4)参数不同。此时,不论有无 virtual 关键字,基类的函数将被隐藏(注意别与重载以及覆盖混淆) 。
(5)参数相同,但是基类函数没有 virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆) 。

下面通过实际的例子来看看具体的调用情况,同时可以用gdb看看运行的内存地址分布

#include <iostream>
using namespace std; 
class A
{
public:
    int oo; 
    char p;
    int pp;
    long long q;
    char a;
public: 
    virtual void g() 
    { 
        cout << "A::virtual void g() called" << endl; 
    }
    virtual void f() 
    { 
        cout << "A::virtual void f() called" << endl; 
    }
/*  void f()
    {
        cout<<"A::void f() called"<<endl;
    }
*/
    void lambda()
    {
        cout << " A::void lambda() called:" << endl;
    }
    //同一个类,通过参数列表不同,重载了lambda()
    //如果定义virtual void lambda(int a,int b),由于子类有不同的返回值,将产生重写overriding失败
    void lambda(int a,int b)
    {
        cout<<"A::void lambda(int a,int b) called:"<<a+b<<endl;
    }
    //同一个类,通过返回值不同,重载了lambda()
    int lambda(long long a,long long b)
    {
        cout<<"A::int lambda(long long a,long long b) called:"<<endl;
        return a>b;
    }
};

class B : public A 
{ 
public:
    //char c;
    long long d;
public:
    //不同类,注意基类g()有virtual关键字,且参数一致,故称之为重写或者覆盖
    void g() 
    {
         cout << "B::void g()" << endl; 
    } 
    //不同类,基类有virtual关键字,同理,属于重写或覆盖
    //同一类,同名函数,参数列表一致,只是加了virtual关键字,怎么算?算重载错误,overload不允许,也是说同一个类不能拿有没有virtual关键字进行重载
    /*  
    virtual void g() 
    { 
        cout << "B::virtual void g()" << endl;
    }*/
    //不同类中,基类g函数为虚函数,函数g改变了参数列表,不是重写或者覆盖,那就是属于重定义
    //同一类中,利用参数列表不同重载了g
    virtual void g(int a,int b){
        cout << "B::virtual g(int a,int b)" << endl;
    }
    //基类f为虚函数,不同类中参数列表一致,重写(覆盖)了f
    void f()
    {
        cout<<"B::void f()"<<endl;
    }
    //不同类中,基类lambda为普通函数,参数列表相同,隐藏或者说重定义了基类的lambda
    void lambda()
    {
        cout << "B::void lambda()"<<endl;
    } 
    //不同类中,基类lambda为普通函数,参数列表一致,返回值不同,重定义了lambda,属于重写?no,只有基类为virtual才算重写,不然归类为重定义
    int lambda(int a,int b)
    {
        cout<<"B::int lambda(int a,int b)"<<endl;
        return a+b;
    }
};
typedef void( *Fun )( void );
int main(int argc, char* argv[])
{
    B b; 
    Fun pFun; 
    cout<<sizeof(b)<<endl;
    //如何找到一个类的虚函数列表,注意这里很好奇gcc为何会每个虚函数地址后面跟着一个0地址作为结尾符
    cout<<"--------------find virtual tables test:-------------"<<endl;
    for(int i = 0 ; i < 5; i=i+2) 
    { 
        pFun = (Fun)*((int*)*(int*)(&b)+i);
        pFun(); 
    }
        //多态测试
    cout<<"----------------A multi situation test:---------------"<<endl;
    A *base = new B();
    base->lambda(2,3);
    long long x=9,y=10;
    base->lambda(x,y);
        base->g();
    base->f();
    //子类虚函数重载测试
    B *b_base = new B();
    cout<<"-----------------------B's f virtual func:--------------"<<endl;
    b_base->lambda();
    b_base->lambda(2,3);
    b_base->f();
    b_base->g();
    b_base->g(3,3);
    //父类函数测试
    cout<<"-------------------------A's func test:------------------"<<endl;
    A *a_base = new A();
    a_base->f();
    a_base->lambda(6,7);
    return 0;
}

输出结果:
48
————–find virtual tables test:————-
B::void g()
B::void f()
B::virtual g(int a,int b)
—————-A multi situation test:—————
A::void lambda(int a,int b) called:5
A::int lambda(long long a,long long b) called:
B::void g()
B::void f()
———————–B’s f virtual func:————–
B::void lambda()
B::int lambda(int a,int b)
B::void f()
B::void g()
B::virtual g(int a,int b)
————————-A’s func test:——————
A::virtual void f() called
A::void lambda(int a,int b) called:13
数据成员地址为:
(gdb) p &b
8 = (B *) 0x7fffffffe530  
(gdb) p &b.oo
9 = (int *) 0x7fffffffe538
(gdb) p &b.p
10 = 0x7fffffffe53c “”  
(gdb) p &b.pp
11 = (int *) 0x7fffffffe540
(gdb) p &b.a
12 = (long long *) 0x7fffffffe548  
(gdb) p &b.d
13 = 0x7fffffffe550 “”
(gdb) p &b.q
$14 = (long long *) 0x7fffffffe558

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值