(注:以下内容是在阅读相关书籍以及课程学习之后的总结内容,如果错误,希望大佬指点!)
1、解释一下C++的多态? 首先,C++的多态机制是指:派生类对象的地址可以赋值给基类指针。对于通过基类指针调用基类和派生类中都有同名、同参数表的虚函数语句,编译时并不需要确定调用的这个函数是基类的函数派生类的,在程序运行到这条语句的时候,如果基类指针指向的是一个基类对象,则基类的虚函数被调用,如果基类的指针指向的是一个派生类的对象,则派生类的虚函数被调用。 其次,多态性只存在子类继承层次中。 另外C++中支持多态性的几种方式: ①隐式转换:从派生类指针或引用转换到其公有基类类型的指针或引用 ②虚拟函数机制:父类指针指向某一个虚拟函数 ③通过dynamic_cast和typeid操作符 2、C++的析构函数能不能写成虚函数?什么时候会用到? 析构函数可以被写成虚函数。 原因是:当基类的指针指向一个派生类类对象的时候,程序运行结束需要调用虚构函数,但是这时候如果子类的析构函数不是虚函数,那么子类对象并没有被析构,会造成内存泄漏。所以将子类的析构函数写成虚函数,然后析构函数就会重置虚表,那么程序在释放基类指针的时候,要想去调用析构函数,必然会查找虚函数表,先去释放子类的析构函数,再释放基类的析构函数。 3、虚函数的调用过程?虚函数表是什么?虚函数表运行时放在哪块内存上 (1)虚函数的调用过程: 当类中存在虚函数的时候,就会产生虚函数表以及指向虚函数表的指针。如果该类作为基类,那么它的派生类会新建一个虚函数表,新的虚表指针会按照基类虚函数表的顺序拷贝基类虚函数表的函数,如果派生类有同名的虚函数,就会将基类的这个虚函数覆盖,如果派生类有新的其他虚函数,也会存放在它的虚表中。 每一个有虚函数的类都有一个虚函数表指针,对象的构造函数会把虚表地址给虚表指针。当通过指针或引用调用一个函数的时候,先通过虚函数指针找到虚函数表,然后根据虚函数在虚函数表中的偏移量来找到所需的函数地址,然后CALL。 (2)虚函数表: 如果一个类中有虚函数,那么这个类就会多四个字节,这四个字节是虚表指针的大小,虚表指针直线虚函数表。虚函数表中存放这个类的所有虚函数地址。 (3)虚函数表运行存放区域: 数据区。 原因:虚函数表是全局共享的元素,排除栈区,并且虚函数表是一个指针数组,每一个元素都是存放这个类的虚函数地址,所以排除代码区,类中虚函数的个数在编译的时候已经确定,所以虚函数表的大小可以确定,因此不需要进行动态分配空间,因此排除堆区。综上所诉,我认为虚函数表存放在数据区。 4、虚基类和抽象类有什么区别? 虚基类指的是基类被虚拟集成到派生类中,例如 class Object : virtual public Bass {……} 抽象类值的是这个类中定义了纯虚函数,例如类中有 virtual void print() = 0,那么这个类不能实例化对象,所以被称为抽象类,需要派生类重写这个基类的纯虚函数。 5、什么是静态绑定和动态绑定? 早期绑定:编译时期就可以确定调用关系 对象名.方法——静态联编 晚绑定:运行过程中才能挑选相应的方法 指针或者引用调用方法采用动态联编 6、你知道哪些函数不能够实现成virtual虚函数? 构造函数是建立虚表的前提,在构造函数中,将虚函数表的地址赋给虚表指针,所以构造函数不能实现成虚函数。 7、多重继承会有什么问题吗? 多重继承表现一个派生类继承了多个基类,比如这个派生类叫D类,这多个基类叫B类,C类,而B类,C类继承了A类,那么B类,C类就会在它们的构造函数中构造A类,如果B,C两个类对A类的初始化不相同,那么C类继承下来之后就会得到两个不同的A类实例,引起二义性。 所以为了避免这种问题,就有了虚继承。将上述出现问题的这种A类通过虚继承的方式让A类的构造由C类进行,从而避免在C类中出现两个不同的A类实例。 8、vfptr和vbptr有什么区别? vbptr是指向虚基类表的指针,虚基类表是存在虚继承的时候产生的,里面是记录每一个类的内存以及这个类到虚基类的偏移量。 vfptr是指向虚函数表的指针,虚函数表是类中有虚函数,就会产生虚函数表,存放虚函数的地址。 9、请描述一下重载、隐藏、覆盖之间有什么不同? 重载:在某一个指定的域内,存在多个函数名相同,但是参数列表不同的函数,这些函数构成了重载(函数的返回值并不参与重载)。 隐藏:在继承关系中,派生类中出现了和基类相同的属性或者方法,那么就会将基类中与之同名的属性或者方法隐藏,从而在调用的时候,在不指明作用域的情况下调用的是派生类的这个属性或者方法。 覆盖:如果派生类也有虚函数,派生类就会拷贝基类的虚表,并将同名的方法进行覆盖。 10、虚函数或者虚继承对对象的内存大小有影响吗? 虚函数对对象的内存大小有影响。 因为虚函数的出现会产生虚函数表和虚函数指针,虽然虚函数表的大小并不在类的大小计算范围内,但是虚函数指针所占的四个字节被加在类的大小中,因此虚函数会对对象的大小有影响,会使得对象的内存大小增加四字节并且会根据内存情况进行内存偏移。 虚继承由于存在虚基指针,所以同理。 11、C++有哪四种类型的强转?分别有哪些作用? ①类型转化 ②去常性转换 ③重新解释转换 ④动态转换 需要继承、虚函数,然后强转子类地址给父类指针,这种转换叫动态转换
class Object
{
public:
virtual void fun() {}
};
class Base :public Object
{
public:
virtual void fun() {}
};
int main()
{
Object* op = NULL;
Base* bp = NULL;
Object obj;
Base base;
op = dynamic_cast<Object*>(&base);
return 0;
}
|