当前位置: 代码迷 >> 综合 >> c++的重要特性之一,继承到底是什么概念呢?
  详细解决方案

c++的重要特性之一,继承到底是什么概念呢?

热度:23   发布时间:2024-02-11 01:00:07.0

----------------------------------------
author:hjjdebug
date: Fri Aug 14 17:25:19 CST 2020
----------------------------------------

继承,简单的说就是你的就是我的.

但到底是什么概念呢?

1. 子类继承父类,是不是把父类的私有成员变量也继承了, 子类对象的大小是多少呢?
2. 子类调用父类的成员函数,汇编程序是不是调整this指针然后才调用的父类地址?
3. 外部调用子类的成员函数, 该成员函数子类没有但其父类有,具体是怎样实现传递的呢?
带着这些问题,我写了简单的测试代码进行了研究.
直入主题,先从main.cpp 说起

 cat main.cpp
#include "C2.h"int main()
{C2 obj;obj.setData(8);obj.printMe(); //直接翻译为调整this指针指向父类,调用父类地址处函数
/*=> 0x00005555555548f8 <+53>:	lea    -0x24(%rbp),%rax //this 指针0x00005555555548fc <+57>:	add    $0x4,%rax	//调整到父类C1a类0x0000555555554900 <+61>:	mov    %rax,%rdi	//调用父类函数地址.0x0000555555554903 <+64>:	callq  0x555555554822 <C1a::printMe()>*/return true;
}

C2类公有继承了C1,C1a类.

$ cat C2.h
#ifndef _C2_H
#define _C2_H
#include "C1.h"
#include "C1a.h"
class C2 : public C1, public C1a
{public:C2(){}~C2(){}void setData(int data);int y;
};
#endif

补全C1.h, C1a.h 及其对应的cpp 文件. C1.cpp, C1a.cpp C2.cpp

hjj@hjj-Inspiron:~/temp$ cat C1.h
#ifndef _CLASS_H
#define _CLASS_H
class C1
{public:C1(){}~C1(){}void setData(int data);int getData();int x;
};
#endif
hjj@hjj-Inspiron:~/temp$ cat C1a.h
#ifndef _C1A_H
#define _C1A_H
class C1a
{public:C1a(){}~C1a(){}void printMe();void setData(int data);int getData();int xa;
};
#endif
hjj@hjj-Inspiron:~/temp$ cat C1.cpp
#include <stdio.h>
#include "C1.h"
void C1::setData(int data)
{x = data;
}
int C1::getData()
{return x;
}
hjj@hjj-Inspiron:~/temp$ cat C1a.cpp
#include <stdio.h>
#include "C1a.h"
void C1a::printMe()
{printf("xa:%d\n",xa);
}
void C1a::setData(int data)
{xa = data;
}
int C1a::getData()
{return xa;
}
hjj@hjj-Inspiron:~/temp$ cat C2.cpp
#include <stdio.h>
#include "C2.h"
void C2::setData(int data)
{printf("c2 SetData()\n");y=data+1;C1::setData(data); //C2 的this 指针与C1的重回,不用调整了/*0x000055555555489a <+40>:	mov    -0x8(%rbp),%rax //this 指针0x000055555555489e <+44>:	mov    -0xc(%rbp),%edx //参数0x00005555555548a1 <+47>:	mov    %edx,%esi	//第一参数送esi0x00005555555548a3 <+49>:	mov    %rax,%rdi	//指针送rdi	0x00005555555548a6 <+52>:	callq  0x5555555547fa <C1::setData(int)>*/C1a::setData(data); //调整this 指针到C1a,然后调用setData(int)/*=> 0x00005555555548ab <+57>:	mov    -0x8(%rbp),%rax //this 指针0x00005555555548af <+61>:	lea    0x4(%rax),%rdx  //调整this 指针0x00005555555548b3 <+65>:	mov    -0xc(%rbp),%eax	//参数0x00005555555548b6 <+68>:	mov    %eax,%esi	//第一参数送esi0x00005555555548b8 <+70>:	mov    %rdx,%rdi	//指针送rdi	, 调用地址0x00005555555548bb <+73>:	callq  0x55555555484a <C1a::setData(int)>*/
}

对于简单的C1,C1a类没什么好说的, 关键是C2类继承了C1,C1A 类, 那它是怎么调用的C1,C1a中的成员函数呢, 注释的汇编代码里

已经给出了答案. 把玩跟踪代码,就可以得出如下结论了. 本帖的核心就是这几行汇编代码.!

结论:
1. 子类继承父类,是不是把父类的私有成员变量也继承了, 子类对象的大小是多少呢?
答:是的. 它是父类的大小加上自己的大小合并为一个大的数据结构.

2. 子类调用父类的成员函数,汇编程序是不是调整this指针然后才调用的父类地址?
答. 是的

3. 外部调用子类的成员函数, 该成员函数子类没有但其父类有,具体是怎样实现传递的呢?
答: 调整this 指针到父类位置,调用父类函数.

所谓继承,就是子类把父类的成员变量全部拿过来,在此基础上补充自己的专有变量,构成一个
更大的数据结构. 当我们在操作不同的变量时,要传递不同父类的this指针.
操作不同的变量,就是调用不同的成员函数包括父类的成员函数.
这就是继承的含义.

当然,继承通常都是public属性,函数与变量根据安全的需要还细分为public,protect,private 属性.

 

  相关解决方案