单一继承
父类先构造!析构的时候是反着的!
尽量把析构函数定义成虚函数,因为将基类的析构函数定义为虚函数后,当利用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