關於動態多態的錯題分析

C++中關於動態多態自己的理解仍然太淺了,對於多次在基類和派生類中來回調用的一些情況,仍然會產生動態多態的情況。
求如下程序的輸出結果:

#include<iostream>
#include<string>
using namespace std;

class Base
{
public:
	virtual void Send()
	{ 
		cout << "\nSend_Base:" << mVal << endl;
	}
	~Base() {}
	void OutPut()
	{
		Send();
	}

	int mVal;
};

class Derive :public Base
{
public:
	Derive() { mVal = 100; }
	virtual void Send()
	{
		mVal++;
		cout << "\nSend_Der: " << mVal << endl;
	}
	void OutPut()
	{
		Base::OutPut();
	}
};

int main()
{
	Derive user;
	Base &base = user;
	base.Send();
	
	Base *p = &base;
	p->OutPut();
	
	user.OutPut();
	return 0;

}

1、分析

(1)、Send() 爲虛函數,當通過基類的引用或指針來調用該虛函數時會產生動態多態。所以Base &base=user 爲基類的引用綁定到派生類的對象上,base.Send()中由於調用的爲虛函數,所以會產生動態多態,此時基類引用綁定的是派生類對象,所以會調用派生類的虛函數。
(2)、第二個輸出對於我來說有很大的迷惑性,由於base是綁定到派生類對象上的引用,所以base相當於派生類對象的別名。Base *p=&base 相當於將派生類對象的地址賦給基類指針,p就成爲指向派生類對象的基類指針,此時若調用虛函數就會產生動態多態的行爲。而迷惑在於p->OutPut(),在類中OutPut()爲普通成員函數,而非虛函數。因此就會調用基類的OutPut函數,但是基類OutPut()函數中又調用了虛函數Send(),而此時的調用對象爲指向派生類的基類指針,因此仍然會產生動態多態的行爲,會調用派生類的虛函數Send()
(3)、第三個是直接使用派生類對象來調用OutPut()函數,所以會直接調用派生類的OutPut成員函數,但是該成員函數又直接調用了基類的OutPut函數,因此會回到基類的OutPut函數中去調用虛函數Send,此時由於調用對象一直是派生類,所以會直接調用派生類所對應的虛函數。在此處是拐了好幾個彎的來回在基類和派生類中進行調用,但是由於是直接通過派生類對象來進行調用的,而不是基類指針或引用來調用,所以在第三個調用中不會產生動態多態。

總結分析:在涉及到虛函數的調用中,有可能會產生動態多態的情況下,首先看是否通過基類的指針或引用來最終調用了虛函數(不管拐了多少彎,最後調用虛函數的時候一定要看,調用的對象是否爲基類指針或引用)。若爲基類指針或引用就會產生多態行爲,否則就只是根據調用函數的對象類型來確定調用的版本。

2、調用結果

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章