补充:
1. 纯虚函数
是一种特殊的虚函数,它的一般格式如下:
class <name>{
virtual<类型><函数名><参数列表> =0;
};
在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函数的作用。
纯虚函数可以让类先具有一个操作名称,而没有操作内容,让派生类在继承时再去具体地给出定义。凡是含有纯虚函数的类叫做抽象类。这种类不能声明对象,只是作为基类为派生类服务。除非在派生类中完全实现基类中所有的的纯虚函数,否则,派生类也变成了抽象类,不能实例化对象。
一般而言纯虚函数的函数体是缺省的,但是也可以给出纯虚函数的函数体(此时纯虚函数仍然为纯虚函数,对应的类仍然为抽象类,还是不能实例化对象)调用纯虚函数的方法为:抽象类类名::纯虚函数名(实参表)
2. 基类指针指向子类对象:
没有指定虚函数, 那么它就只能访问到类型对应的函数
基类指针就只能访问到基类函数
子类指针就只能访问到子类函数
定义了虚函数就可以访问到子类对应的函数。
for example:
//基类:
class A {
public:
A();
virtual ~A();
void f1();
virtual void f2();
virtual void f3()=0;//纯虚函数
};
//子类:
class B:public A{
public:
B();
virtual ~B();
void f1();
virtual void f2();
virtual void f3();
};
//主函数:
int main(int argc,char * argv[]) {
A *m_j = new B();
m_j -> f1();//调用基类的函数
m_j -> f2();//重写函数,调用的是子类的函数
m_j -> f3();//虚函数,基类中的虚函数不用写具体的函数体。
delete m_j;
return 0;
}
3. 构造函数不能为虚函数
1每个类都有一个虚函数表。虚函数对应一个指向vtable虚函数表的指针,如果构造函数是虚的,就需要通过 vtable来调用,可是对象还没有实例化,也就是内存空间还没有,不能找vtable。所以构造函数不能是虚函数。
2虚函数主要用于在信息不全的情况下,能使重载的函数得到对应的调用。构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀。所以构造函数没有必要是虚函数。虚函数的作用在于通过父类的指针或者引用来调用它的时候能够变成调用子类的那个成员函数。而构造函数是在创建对象时自动调用的,不可能通过父类的指针或者引用去调用,因此也就规定构造函数不能是虚函数。
3调用构造函数时还不能确定对象的真实类型(因为子类会调父类的构造函数);而且构造函数的作用是提供初始化,在对象生命期只执行一次,不是对象的动态行为,也没有必要成为虚函数。
参考:
构造函数为什么不能是虚函数
- 是不是可以把每个函数都声明为虚函数?
不行,虚函数是有代价的。
每个虚函数都必须维护一个虚函数表,使用虚函数的时候都会产生一个系统开销。