在设计类时,虚函数着重体现基类或接口的设计原则。虚函数应能表达你所想要表达的,使得派生类在重载是不存在歧义。虚函数存在以下用法:
1、虚析构函数
虚析构函数表示本类为抽象基类,用户可以从本类派生,用户也可通过基类对象管理派生类对象。public的虚析构函数比较常用,表示用户可以管理对象的生命期。protected的虚析构函数表示用户只能通过本对象使用派生类对象,但不包括生命期管理。private的虚析构函数极少使用。
一个常见的错误是将接口的析构函数定义为public的虚析构函数。我个人不是很赞同这一点,他混淆了抽象对象和接口的本质区别,抽象对象表示派生类是基类的一种,如猴子是动物的一种,这种特性是运行时不可变更的,所以一般体现为单继承。而接口表示一个具有某种特征或者角色的对象,这种特性可以在运行时改变,所以一般体现为多继承。如某个人既有老师角色也有学生角色,四年以后,他的学生角色可能没有了,但该对象依然存在,所以对象的生命期不应该通过接口来管理,只能通过抽象基类来管理。所以接口的析构函数应体现为保护的非虚析构函数。实例如下:
class CAnimate
{
public:
...
virtual ~CAnimate(void){}
...
};
class IStudent
{
...
protected:
~IStudent(void){}
};
2、public的虚函数
public的虚函数体现了抽象类或接口的本质,即体现抽象类或接口的不变式。这是虚函数使用最广泛的方式,然而我个人并不赞同抽象类的public虚函数,应为它使得派生类的重载实现引入了一定的歧义。实例如下:
class CAnimate
{
public:
virtual void DoSomething(void);
...
};
class CBird : public CAnimate
{
public:
virtual void DoSomething(void)
{
....
CAnimate::DoSomething(); //要不要调用基类的实现呢? 不知道,模糊中
}
};
所以代之以如下:
class CAnimate
{
public:
void DoSomething(void) {DoSomethingImp()l}
protected:
virtual void DoSomethingImp(void);
};
class CBird : public CAnimate
{
protected:
virtual void DoSomethingImp(void)
{
....
CAnimate::DoSomethingImp(); //必须要调用基类的实现, 保护的虚函数正是表示派生类和基类合作完成一件事
}
};
2、protected虚函数
保护的虚函数表派生类和基类合作完成一件事,在派生类的实现中必须调用基类的实现。当然是采用前调用还是后调用依然比较模糊。
3、private虚函数
私有的虚函数表示要么是派生类完成一件事,要么是基类完成,但不能共同完成。
胡乐秋
2010/9/6
http://blog.csdn.net/hlqyq