面试题答案
一键面试- 模板实例化过程:
- 当创建
DerivedTemplate<int>
对象时,首先进行模板实例化。编译器会根据模板参数int
生成TemplateBase<int>
和DerivedTemplate<int>
的具体类定义。这是编译时的行为。 - 模板实例化是根据具体的模板参数将模板类生成具体的类,在此过程中,编译器会检查模板代码的语法正确性,但不会执行构造函数等成员函数的代码。
- 当创建
- 构造函数非虚特性与对象创建:
- 对象创建顺序:在创建
DerivedTemplate<int>
对象时,先调用TemplateBase<int>
的构造函数,再调用DerivedTemplate<int>
的构造函数。这是因为构造函数是非虚的,构造过程是从基类到派生类逐步进行。这种顺序是固定的,与虚函数机制无关。 - 构造函数非虚原因:构造函数的主要任务是初始化对象的成员变量。如果构造函数是虚的,由于虚函数调用需要通过虚函数表,而在对象构造过程中,虚函数表可能还未完全初始化,这会导致未定义行为。所以构造函数不能是虚的。
- 对象创建顺序:在创建
- 对虚函数机制的影响:
- 编译时:
- 在编译时,编译器根据对象的静态类型来确定对虚函数的调用。例如,如果有一个指向
DerivedTemplate<int>
对象的TemplateBase<int>*
指针,在编译时编译器会根据TemplateBase<int>
类的定义来检查对虚函数的调用是否合法。 - 模板实例化过程中,编译器会为
TemplateBase<int>
和DerivedTemplate<int>
分别生成虚函数表(如果有虚函数)的布局信息,这为运行时的虚函数调用奠定基础。
- 在编译时,编译器根据对象的静态类型来确定对虚函数的调用。例如,如果有一个指向
- 运行时:
- 在运行时,虚函数的调用是基于对象的实际类型(动态类型)。当通过
TemplateBase<int>*
指针调用虚函数时,如果实际指向的是DerivedTemplate<int>
对象,会调用DerivedTemplate<int>
重写的虚函数版本。这是因为对象在构造完成后,虚函数表指针会正确指向相应类的虚函数表,运行时系统根据虚函数表来实现动态绑定。 - 由于构造函数非虚,在构造
DerivedTemplate<int>
对象的过程中,当调用TemplateBase<int>
的构造函数时,对象的实际类型被视为TemplateBase<int>
,此时如果在TemplateBase<int>
构造函数中调用虚函数,会调用TemplateBase<int>
版本的虚函数,而不是DerivedTemplate<int>
重写的版本。只有在整个DerivedTemplate<int>
对象构造完成后,虚函数的动态绑定才能按预期工作。
- 在运行时,虚函数的调用是基于对象的实际类型(动态类型)。当通过
- 编译时: