300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > c++继承 基类 派生类 虚函数

c++继承 基类 派生类 虚函数

时间:2024-05-20 22:28:42

相关推荐

c++继承 基类 派生类 虚函数

继承

类和类的关系有组合、继承和代理。继承的本质就是代码复用。子类继承父类中的一些东西,父类也称为基类,子类也称为派生类。派生类继承了基类除构造函数以外的所有成员。

继承的方式

继承方式有public(公有继承)、private(私有继承)和protected(保护继承)。基类中不同访问限定符下(public、protected、private)的成员以不同的继承方式继承,在派生类中的访问限定也不同,具体如下:

基类的布局优先于派生类

#include<iostream>class Base{public:Base(int a):ma(a){}public:int ma;};class Derive :public Base{public:Derive(int b):mb(b), Base(b){}public:int mb;};int main(){Derive(20);return 0;}

我们可以在开发人员命令提示符窗口中进入当前源文件的目录,使用cl ConsoleApplication5.cpp /d1reportSingleClassLayoutDerive来查看派生类Derive的布局如下:

由图可见,基类的布局优先级高于派生类。那么派生对象的构造方式是怎么样的呢?

1.调用基类的构造函数

2.调用派生类的构造函数

派生类的析构可想而知:

1.调用派生类的析构函数

2.调用基类的析构函数

虚函数

如下程序:

class Base{public:Base(int a):ma(a){}virtual void Show(){std::cout << "Base:Show ma=" << ma << std::endl;}protected:int ma;};class Derive :public Base{public:Derive(int b):mb(b), Base(b){}void Show(){std::cout << "Derive:Show mb=" << mb << std::endl;}protected:int mb;};int main(){std::cout << "sizeof(Base):" << sizeof(Base) << std::endl;std::cout << "sizeof(Derive):" << sizeof(Derive) << std::endl;Base* pb=new Derive(20);std::cout << typeid(pb).name() << std::endl;std::cout << typeid(*pb).name() << std::endl;pb->Show();return 0;}

运行结果如下:

上面结果说明一个基类的指针是可以指向其派生类对象的。基类中含有虚函数,那么基类布局中存在一个虚函数指针,指向虚函数表;且其派生类中与其同名同参的函数不需要加virtual也是虚函数。此时基类和派生类的布局如下:

vfptr的指针大小为4(32位机器)。因此基类字节数为8,派生类为12。vfptr指针指向的vftable(虚函数表)中,&Base_meta中存放了RTTI信息(运行时类型信息),也就是class Base,0表示偏移,&Base::Show表示虚函数的入口地址。typeid()可以动态获取类型。

main函数中,生成了一个派生类对象。pb是一个指针类型,它的类型只和定义点有关,因此打印出来pb的类型为class Base类型;而pb是一个自定义类型,动态获取类型时,先通过指针pb解引用找到派生类对象,通过vfptr找到vftable,&Derive_meta中存放了派生类的RTTI信息,其中存放的是class Derive,因此*pb的类型是class Derive。

pb指针调用Show()函数时,发生了动多态。首先通过指针所指向的对象找到vfptr,再找到vftable,获取到Show函数的入口地址,此时 &Derive::Show中存放的是派生类的虚函数入口地址,因此调用的是派生类中的Show()函数。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。