面向对象 - 继承

什么是继承

继承的本质是复制,编译器按照一定规则把基类代码复制到子类。

先写一个没有继承的类,Man中2个字段x和y:

class Man 
{
public:
    int x;
    int y;
};

int main()
{
    Man man;
    man.x = 1;
    man.y = 2;
    return 0;
}

查看反编译代码:

53:     Man man;
    54:     man.x = 1;
C7 45 F4 01 00 00 00 mov         dword ptr [ebp-0Ch],1  
    55:     man.y = 2;
C7 45 F8 02 00 00 00 mov         dword ptr [ebp-8],2

再写一个有继承的类,子类Man继承基类Human。Man中两个字段:x和y。

class Human
{
public:
    int x;
};

class Man : public Human
{
public:
    int y;
};

int main()
{
    Man man;
    man.x = 1;
    man.y = 2;
    return 0;
}

反汇编:

46:     Man man;
    47:     man.x = 1;
C7 45 F0 01 00 00 00 mov         dword ptr [ebp-10h],1  
    48:     man.y = 2;
C7 45 F4 02 00 00 00 mov         dword ptr [ebp-0Ch],2

我们发现反汇编代码是一样的,由此可以得出结论:继承的本质是赋值,编译器帮助我们把基类的代码复制到子类,帮助我们减少写代码的工作量。

继承相关特性:

1、因为编译器把基类代码拷贝到子类,所以可以用基类的指针指向子类的对象。

Human* pt = &man;	
printf("x= %d", pt->x);

2、如何访问y。但是编译器认为Human只有x,不允许访问y。通过上面反编译代码,我们知道结构y的地址在x地址的下面,所以可以通过pt+1获取到y地址。代码如下:

Man man;
man.x = 1;
man.y = 2;

Human* pt = &man;
//打印y的值
printf("y= %d", *(int*)(pt + 1));

3、如何用子类的指针访问基类的对象。通过上面分析,我们知道子类代码不存在基类中,编译器当然也知道,所以编译器不允许直接访问。可以尝试通过指针访问,但是这种访问是错误的,这个位置上存的是垃圾数据,VS编译器无法编译。

Human human ;
human.x = 3;

Man* man = (Man*)&human;
printf("man.x= %d\n", man.x);
printf("man.y= %d\n", man.y);

4、当基类还存在基类时,编译器会把基类和基类的基类都代码复制到子类。
5、如果子类和基类中有群成员重名,使用::符号进行赋值。

class Human
{
public:
    int x;
};

class Man : public Human
{
public:
    int x;
};

int main()
{
    Man man;
    man.x = 1;
		//等于 man.x = 2;
    man.Man::x = 2;
    man.Human::x = 3;
}

6、基类私有成员和函数也会被继承。

class Human
{
public:
    Human() {
        x = 1;
    }
private:
    int x;
};

class Man : public Human
{
public:
    int y;
    Man() {
        y = 2;
    }
};

int main()
{
    Man man;
    int* ptr = (int*)&man;
    printf("x=%d\n", *ptr);         //访问x
    printf("y=%d\n", man.y);        //访问y
    printf("y=%d\n", *(ptr+1));     //访问y
    
    return 0;
}

编译器不允许使用私有成员,但我们通过指针可以访问,通过*ptr 可以访问x。

7、构造函数调用顺序。当子类初始化时,会先调用基类构造函数,再调用子类构造函数。

8、如果函数原型相同,则会覆盖。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值