C++类对象中虚函数与多态性的实现

版权声明:版权归作者祝枫所有,欢迎保留原文链接进行转载。 https://blog.csdn.net/Vince_ZHU/article/details/82989659

在面向对象编程时,有时会遇到这种需求:我们希望同一个方法在基类和派生类中实现不同的功能,即体现出行为上的多态性。一般有两种方法可以实现这种需求,其一是在派生类中重新定义基类中方法,其二是使用虚函数。这里主要记录利用虚函数实现多态性的方法。

类中虚函数的定义方法

虚函数使用关键词virtual进行标识。通过一个例子加深对虚函数的理解,一个银行需要开发两类账户,一类是基本账户BaseAcct,另一类是高级账户PlusAcct,具有透支功能,多显示透支上限和透支额度信息。两个账户的基本特征为:

class BaseAcct{
	private:
	    string fullName;
	    long balance;
	public:
	    BaseAcct(const stirng &s="Nullbody", long bal=0.0);
	    void Deposit(double amt);  //存款
	    virtual void Withdraw(double amt);  //取款,无透支功能
	    virtual void ViewAcct() const;
	    virtual ~BaseAcct() {};  //基类析构函数最好定义为虚函数以保证正确的析构顺序
	};
class PlusAcct:public BaseAcct{
	private:
	    double maxLoan;  //透支上限和透支额度
	    double owesBank;
	public:
	    PlusAcct(const stirng &s="Nullbody", long bal=0.0, double ml=500, double ob=0.0);
	    virtual void Withdraw(double amt);  //取款,有透支功能
	    virtual void ViewAcct() const;  //多显示透支上限和透支额度
	    ~PlusAcct() {};  //析构函数是自带默认的,可以不写
	};

派生类PlusAcct中对基类BaseAcct中的虚函数Withdraw()和ViewAcct()进行改写,实现了不同的功能。可以在后续进行重写,这是虚函数的特点。但是重写时要注意,重写的函数其函数原型要保持与基类中完全相同,否则编译器将会产生warning。只有返回值可以由基类指针/引用改变为派生类指针/引用,称之为返回值协变。

上述特点与重载不同,重载中要求函数的参数列表必须不同才能实现重载。

虚函数的工作原理

编译器在处理虚函数的方法是为每一个对象增加一个隐藏成员,其中保存了一组指向虚函数数组地址的指针,一般称之为虚函数表。

动态联编与多态性

在管理BaseAcct和PlusAcct帐户时,不能用一个数组去存储BaseAcct和PlusAcct对象,因为两者的类型不同。但是却可以创建指向BaseAcct类的指针数组,然后根据需要让其指向BaseAcct或PlusAcct对象。因为编译器在处理虚函数时是采用动态联编的,即在程序运行的时候再选择正确的虚方法。而这种动态联编的特性,可以让同一个数组中的指针指向不同的基类或者派生类,并让其表现出不同的特性,即为多态性。

通过指针或者引用调用方法时,若为virtual,将根据指针或者引用指向对象选择方法;若非virtual,将根据指针或者引用本身的类型选择方法。这个特性是类对象实现多态性的基础。

祝枫
2018年10月9日

猜你喜欢

转载自blog.csdn.net/Vince_ZHU/article/details/82989659