上一次,用多态解决了这个问题,对自己转换指针类型的做法仅仅提到了一下。后来想想,这种讲解不令人满意,因为,用多态解决的前提是,想放入的多个对象必须派生自同一个基类,必须有统一的接口。这也说明了,为什么在面向对象的设计中必须有一个公有的基类,任何类必须由它派生,哪怕你仅仅写一个“Hello World”。太死板了,不是吗?
但是,任何人都有考虑不周的时候,假设现在你的程序写了一半了,突然发现,你需要把原来不相关的(仅仅是因为当初认为他们不相关)的对象放入一个容器(数组、链表……),难道还去修改类的继承关系?——当然,你可以用多重继承,在你需要放入的对象的上面,再套上一个外壳;但是,我建议你不要这么做,理由是多重继承很复杂,常常会出现意想不到的事情,没有必要仅仅为了这个应用而给自己找麻烦,你可以采取下面的做法,你可以把它看作是人工实现的多态:
//-----------------------------------------Timer.h---------------------------
#ifndef Timer_H
#define Timer_H
#include <windows.h>
class Timer
{
public:
Timer() { QueryPerformanceFrequency(&Frequency); }
inline void Start() { QueryPerformanceCounter(&timerB); }
inline double GetTime()
{
QueryPerformanceCounter(&timerE);
return (double)(timerE.QuadPart - timerB.QuadPart) / (double)Frequency.QuadPart * 1000.0;
}
private:
LARGE_INTEGER timerB, timerE, Frequency;
};
#endif
//-------------------------------------Timer.h END---------------------
#include <iostream>
#include <vector>
#include “Timer.h”
using namespace std;
class a//使用多重继承的外壳
{
public:
virtual void run() = 0;
};
class a1 : public a
{
public:
void say() {cout << "I am class a1." << endl;}
void run() {say();}
};
class a2 : public a
{
public:
void speak() {cout << "I am class a2." << endl;}
void run() {speak();}
};
class a1a2//a1、a2的共有类
{
public:
a1a2(a1* p) : pa1(p), type(ta1) {}
a1a2(a2* p) : pa2(p), type(ta2) {}
void run()
{
switch (type)
{
case ta1:
pa1->say(); break;
case ta2:
pa2->speak(); break;
default: break;
}
}
private:
union { a1* pa1; a2* pa2;};
enum { ta1, ta2 };
int type;
};
void m1()//使用人工方法的“多态”
{
Timer d; d.Start(); vector<a1a2> b; int i;
for(i = 0; i < 4; i++)
{
b.push_back(a1a2(new a1()));
b.push_back(a1a2(new a2()));
}
//for (i = 0; i < 8; i++) b[i].run();
cout << d.GetTime() << endl;
}
void m2()//多重继承的方法
{
Timer d; d.Start(); vector<a* > b; int i;
for(i = 0; i < 4; i++)
{
b.push_back(new a1());
b.push_back(new a2());
}
//for (i = 0; i < 8; i++) b[i]->run();
cout << d.GetTime() << endl;
}
int main()
{
m1(); m2();
return 0;
}
实际上,这里a1、a2都是基类,但我们可以假设,他们都是别的类派生出来的,当你需要使用多态方法的时候,要在他们的继承关系上把外壳加上,所以,就是多重继承了,我想你不会挑我这个。人工方法的实现,和多态的原理很像,就是根据实际上存储指针的类型,调用相应的类的函数。
知道时间函数后,就好像上了瘾,总要测试一下。人工“多态”方法和多态方法哪个更快呢?我不列举数据了,试验表明,人工方法比系统的多态要快,VC6大概要快0.8倍,BCB6大概0.3倍。BCB6的多态要比VC6的快,但是人工方法比VC6的慢。我尽可能的少用了短循环,估计这方面的影响不大。
即使这种方法要比系统的多态快一些,但我还是不鼓励用这种方法来代替多态,除非你在C上使用(人家没有多态,那是没办法了)。因为,编程是个向后的过程,你很难预料后面发生什么,使用多态和这个要求是相符的,你可以为后面的工作预先定下一个框架。而这种方法是向前的一个总结过程,对于后面的变化,必须随时修改,很像现在的程序打补丁,是对前面构想不周的一个补充。所以这两种方法不是互相代替,而是互相补充。