理解继承、虚函数与多态
示例代码(摘自《深入浅出MFC》)
第一节:
使用VS2005生成一个console程序,添加MyTestClass.h将如下代码添加到该头文件中#include "string.h"/* CEmployee是基类 CWage、CManager为CEmployee的派生类 CSales为CWage的派生类*/
// Base Class 职员class CEmployee{private: char m_Name[30];
public: CEmployee(); CEmployee(const char *nm) { strcpy_s(m_Name,sizeof(m_Name),nm); } void getname() { printf("%s/n",m_Name); }};
class CWage:public CEmployee{private: float m_wage; float m_hours;public: CWage(const char *nm) : CEmployee(nm) { m_wage = 250.0; m_hours = 40.0; } float computePay() { return (m_wage * m_hours); }};
class CSales:public CWage{private: float m_comm; float m_sale;public: CSales(const char *nm):CWage(nm) { m_comm = m_sale = 0.0; } void SetCommission(float comm) { m_comm = comm; } float computePay() { return ( CWage::computePay() + m_comm * m_sale); }};
class CManager:public CEmployee{private: float m_salary;public: CManager(const char *nm):CEmployee(nm) { m_salary = 1500.0; } void setSalary(float salary) { m_salary = salary; } float computePay() { return m_salary; }};
添加一个.cpp文件,并在cpp文件中添加如下代码:#include "stdafx.h"#include "MyTestClass.h"
int _tmain(int argc, _TCHAR* argv[]){ CManager aManager("管理"); CSales aSales("销售"); CWage aWager("其它");
CEmployee *pEmployee[3]; pEmployee[0] = &aManager; pEmployee[1] = &aSales; pEmployee[2] = &aWager;
for (int i=0; i<3; i++) pEmployee[i]->getname();
return 0;}
输出结果会怎样呢?因为 CWage、CManager为CEmployee的派生类,CSales为CWage的派生类,所有的对象均从CEmployee派生出来,所以都会继承CEmplyee的成员,即所有的对象都有和getname函数。但是同一函数怎样处理不同的数据?为什么只调用了getname却可以处理不同的名称?实际上是this指针的功能,编译器在编译过后生成的代码中会添加一个隐匿的参数:this指针。在类的成员变量前面会加入this->来标志究竞是哪个对象正在处理。实际上当在处理CManager aManager("管理");时基类CEmployee中的m_Name成员变量前面加入了一个this指针,该指针就指向了对象aManager。所以程序输出结果为:管理销售其它
现在我如果把CSales稍为改造一下,变成如下的样子,其它代码不作改动class CSales:public CWage{private: float m_comm; float m_sale;
char szName[30];public: CSales(const char *nm):CWage(nm) { m_comm = m_sale = 0.0; strcpy(szName,nm); } void SetCommission(float comm) { m_comm = comm; } float computePay() { return ( CWage::computePay() + m_comm * m_sale); } void getname() { printf("销售类中的:%s/n",szName); }};
我只是在CSales中加入了一个与基类相同的函数getname,那程序的输出结果会怎样呢?程序将输出基类中的字符串呢?还是子类中的字符串呢?运行一下,输出结果如下管理销售其它为什么在第二行中不输出 “销售类中的:销售”这个字符串呢?哦,原因是:如果基类与派生类都定义了“相同名称这成员函数”,那么通过对象指针调用成员函数时,到底调用哪一个函数,必须视该指针的原始类型而定,而不是视指针实际所指的对象的类型而定。上面的例子中,指向对象的指针定义为CEmployee *pEmployee[3];那指针的原始类型为CEmployee,所以当然会执行CEmployee中的getname了。所以会有如上的输出结果。为了验证这个结论,我们再将.cpp文件修改一下,在for循环前面加入这么两行代码 CSales *pSales = &aSales; pSales->getname();或干脆点,变成这样的 CSales *pSales; pEmployee[1] = pSales = &aSales; pSales->getname();同样是把aSales对象的地址赋给两个指针,执行结果会一样吧?呵呵,运行一下:销售类中的:销售管理销售其它结果如上,看样子是与该指针的原始类型决定了成员函数的调用。