虚函数面临的问题
一般来说,虚成员函数可以满足对象的动态类型匹配的需要。一个定义良好的类层次结构应该为基类中声明的每一个虚成员函数定义有意义的操作。然而事情并非总是这样美妙。我们举一个例子,假设有一个家用电器管理系统,可以管理电扇、电视机等。 为了能够实现统一管理,我们设计一个抽象基类 HomeElectricDevice 来定义一些公共操作。
class HomeElectricDevice { public: virtual void Open() = 0; //打开 virtual void Close() = 0; //关闭 // Other methods private: // common attributes.. };
在基类的下面有一些派生类来管理不同的电器,如 ElectricFan ,Television ,它们 实现了抽象基类的方法,并增加了一些特殊的操作。
class ElectricFan: public HomeElectricDevice // 电扇 { public: virtual void Open(){...} //打开 virtual void Close(){...} //关闭 // Other methods private: // attributes.. }; class Television: public HomeElectricDevice // 电视机 { public: virtual void Open(){...} //打开 virtual void Close(){...} //关闭 // Other methods virtual void PlayVCD(); //播放VCD private: // attributes.. };
显然,电扇和电视机有一些不同,例如电视机可以播放 VCD 而电扇不能。假设有个控制类 DeviceControl 统一控制这些设备
enum Command{ OPEN ,CLOSE,PLAY _VCD,... }; class DeviceControllor //控制类 { public: Command GetCommand() { ... } //从其他渠道获取命令 void ControlThem(HomeElectricDevice &); //控制方法 //… };
在该系统中,统一的控制方法应该能够对每一个控制命令做出恰当的反应,但 是由于 HomeElectricDevice 是一个不能实例化的抽象类,因此该函数只能接受派生类的对象。
void DeviceControllor: :ControlThem(HomeElectricDevice &device) { Command cmd = GetCommand(); switch(cmd) { case OPEN: device.Open(); break; case CLOSE: device.Close(); break; case PLAY_VCD: //这里遇到了难题!该如何实现? } }
虽然我们初步实现了一个多态类层次结构,并且 Open()、Close()等函数并不依赖于参数的确切类型。但是我们注意到,在实现PlayVCD()时遇到了困难,因为 Television的成员函数 PlayVCD()并非公共接口。你可能会说"把它提升到根类中" 但是如果这样做就是一个设计概念上的错误,因为并不是每一种电器都支持播放功能。但是当控制电视机时 ControlThem() 必须能够支持播放功能。此时,以虚函数形式表现的普通多态就显得力不从心了。 ControlThem()只知道它的参数是 HomeElectricDevice 派生类的对象,然而这个信息不足以告诉它当前待处理的具体对象能否播放 VCD 。在这种情况下仅有静态类型检查和虚函数机制已经不足以解决所有的问题。怎么办呢?
显然,为了正常地处理所有可能的对象, ControlThem()需要知道更多的关于参数运行时的类型信息。这正是需要 RTTI (运行时类型信息,运行时类型识别)的地方。
浙公网安备 33010602011771号