8 继承和多重继承

单一继承

父类先构造!析构的时候是反着的!

尽量把析构函数定义成虚函数,因为将基类的析构函数定义为虚函数后,当利用delete删除一个指向派生类定义的对象指针时,系统会调用相应的类的析构函数。而不将析构函数定义为虚函数时,只调用基类的析构函数。

本类中成员是其他自定义类,根据顺序构造。

根据上图可以看出  子类 *b = (子类*)a是错误的,因为子类的指针访问越界了 【a是父类

根据上图可以看出 子类的内存布局,那么this+0处的虚表最后被修改成子类的虚表了 如果子类重写了虚函数,那么通过父类指针调用某个虚函数执行的是子类的虚函数,这样就形成了多态。


class ren
{
public:
	virtual shuohua()
	{
	}
	//定义成纯虚函数
 
};
class zhongguo:public ren
{
public:
	virtual shuohua(){
		printf("zhongguoren");
	}
};
class riben:public ren
{
public:
	virtual shuohua()
	{
		printf("ribenren");
	}
};

int main(int argc, char* argv[])
{ 
    ren *p1=new zhongguo();
	ren *p2=new riben();
	p1->shuohua();//多态 通过父类ren的指针调用子类的虚函数【想要多态必须用指针】
	p2->shuohua();
	delete p1,p2;
	return 0; 
}

 

 


 

多重继承

 

#include "stdafx.h"
#include "string.h"
#include "stdlib.h"
//#pragma pack(2);
 
  
class A
{
public:
	A(){strcpy(str,"AAAAAAAAAAA");};
	virtual vir1(){printf("A vir1()");	}
	virtual vir2(){printf("A vir2()");	}
	virtual vir3(){printf("A vir3()");	}
	char str[0x0C];
};
class B
{
public:
	B(){strcpy(str,"BBBBBBBBBBB");};
	virtual vir1(){printf("B vir1()");	}
	virtual vir2(){printf("B vir2()");	}
	virtual vir3(){printf("B vir3()");	}
	char str[0x0C];
};
class C:public B ,public A
{
public:
 	C(){strcpy(str,"CCCCCCCCCCC");};
	virtual vir1(){printf("C vir1()");	}
	virtual vir2(){printf("C vir2()");	}
	virtual vir3(){printf("C vir3()");	}
	char str[0x0C];
};
int main(int argc, char* argv[])
{ 
   A *c=new C();
   c->vir1();
   system("pause");
   return 0;
}

类C的构造函数里面按继承父类的顺序调用父类的构造函数 

虚表指针个数:有几个父类便会出现对应个数的虚表指针

A *c=new C();
   c->vir1();//转换父类指针时,需要调整到父类A对象的首地址


抽象类

纯虚函数由于没有实现代码,编译器为了方式误调用,讲虚表中的首地址替换成函数_purecall

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值