【普通函数和虚函数调用的区别?】
答:这个区别很重要:
在抽象的继承模型中叫做多态
就是说,你定义一个类,他们具有相同的接口
但是具体的不同的类又有不同的特征,实现之类可能也完全不同
但是你可以用共同的基类指针来管理
虚函数在实现的时候,其实是在类里建了一个隐含的成员变量,是一个指向函数的指针
所以从基类调用也可以调用到继承类定义的成员函数。
【能否在构造函数里调用虚函数?】
先来看一段程序:
#include<iostream>
using namespace std;
class Base
{
public:
Base()
{
Fuction();
}
virtual void Fuction()
{
cout << "Base::Fuction" << endl;
}
};
class A : public Base
{
public:
A()
{
Fuction();
}
virtual void Fuction()
{
cout << "A::Fuction" << endl;
}
};
// 这样定义一个A的对象,会输出什么?
int main()
{
A a;
return 0;
}
可能很多人说输出结果是:
A::Function
A::Function
如果是这样,首先我们回顾下C++对象模型里面的构造顺序,在构造一个子类对象的时候,首先会构造它的基类,如果有多层继承关系,实际上会从最顶层的基类逐层往下构造(虚继承、多重继承这里不讨论),如果是按照上面的情形进行输出的话,那就是说在构造Base的时候,也就是在Base的构造函数中调用Fuction的时候,调用了子类A的Fuction,而实际上A还没有开始构造,这样函数的行为就是完全不可预测的,因此显然不是这样,实际的输出结果是:Base::Function
A::Function
再次小结下:
1)当在构造基类部分时,派生类还没被完全创建,从某种意义上讲此时它只是个基类对象。即当Base::Base()执行时Derive对象还没被完全创建,此时它被当成一个Base对象,而不是Derive对象,因此Foo绑定的是Base的Foo。
2)基类部分在派生类部分之前被构造,当基类构造函数执行时派生类中的数据成员还没被初始化。如果基类构造函数中的虚函数调用被解析成调用派生类的虚函数,而派生类的虚函数中又访问到未初始化的派生类数据,将导致程序出现一些未定义行为和bug
所以不要在构造函数里调用虚函数
【当类中定义了虚函数,但是没有定义构造函数,编译器会为虚函数合成构造函数吗?如果合成,会做什么事?】
会的,因为编译器会为带有虚函数的成员合成一个虚表
【带有虚函数的类和普通的类有什么区别:】
多了四个字节(虚表指针)