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

----------------------------------------
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 
 */

	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 
#include "C1.h"
void C1::setData(int data)
{
	x = data;
}
int C1::getData()
{
	return x;
}
hjj@hjj-Inspiron:~/temp$ cat C1a.cpp
#include 
#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 
#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	//第一参数送esi
     0x00005555555548a3 <+49>:	mov    %rax,%rdi	//指针送rdi	
     0x00005555555548a6 <+52>:	callq  0x5555555547fa 
	 */
	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	//第一参数送esi
     0x00005555555548b8 <+70>:	mov    %rdx,%rdi	//指针送rdi	, 调用地址
     0x00005555555548bb <+73>:	callq  0x55555555484a 
	 */
}

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

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

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

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

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

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

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

 

你可能感兴趣的:(c++,编程,c++,继承)