2.2 纯虚函数

  如下声明表示一个函数为纯虚函数:

class A
{
public:
virtual void foo()=0; // =0标志一个虚函数为纯虚函数
};

  一个函数声明为纯虚后,纯虚函数的意思是:我是一个抽象类!不要把我实例化!纯虚函数用来规范派生类的行为,实际上是所谓的“接口”。它告诉使用者,我的派生类都会有这个函数。

  2.3 虚析构函数

  析构函数也可以是虚的,甚至是纯虚的。例如:

class A
{
public:
virtual ~A()=0; // 纯虚析构函数
};

  当一个类打算被用作其它类的基类时,它的析构函数必须是虚的。考虑下面的例子:

class A
{
public:
A() { ptra_ = new char[10];}
~A() { delete[] ptra_;} // 非虚析构函数
private:
char * ptra_;
};
class B: public A
{
public:
B() { ptrb_ = new char[20];}
~B() { delete[] ptrb_;}
private:
char * ptrb_;
};
void foo()
{
A * a = new B;
delete a;
}

  在这个例子中,程序也许不会象你想象的那样运行,在执行delete a的时候,实际上只有A::~A()被调用了,而B类的析构函数并没有被调用!这是否有点儿可怕?

  如果将上面A::~A()改为virtual,可以保证B::~B()也在delete a的时候被调用了。因此基类的析构函数都必须是virtual的。

  纯虚的析构函数并没有什么作用,是虚的够了。通常只有在希望将一个类变成抽象类(不能实例化的类),而这个类又没有合适的函数可以被纯虚化的时候,可以使用纯虚的析构函数来达到目的。

  2.4 虚构造函数

  构造函数不能是虚的。

  3、虚函数使用技巧

  3.1 private的虚函数

  考虑下面的例子:

class A
{
public:
void foo() { bar();}
private:
virtual void bar() { ...}
};
class B: public A
{
private:
virtual void bar() { ...}
};

  在这个例子中,虽然bar()在A类中是private的,但是仍然可以出现在派生类中,并仍然可以与public或者protected的虚函数一样产生多态的效果。并不会因为它是private的,发生A::foo()不能访问B::bar()的情况,也不会发生B::bar()对A::bar()的override不起作用的情况。

  这种写法的语意是:A告诉B,你好override我的bar()函数,但是你不要管它如何使用,也不要自己调用这个函数。