【校園招聘】一道筆試題看c++中virtual覆蓋

pengfoo發表於2012-09-17
#include<iostream>
using namespace std;

class A
{
 public:
	void virtual f()
	{
		cout<<"A"<<endl;
	}	
};

class B:public A
{
 public:
	void /*virtual*/ f()     //virtual可以省略,也可以不省略,效果相同。
	{
		cout<<"B"<<endl;
	}
};

int main()
{
	A *pa = new A();
	pa->f();

	B *pb = (B*)pa;
	pb->f();

	delete pa,pb;

	pa = new B();//多型
	pa->f();

	pb = (B*)pa;
	pb->f();

	return 0;
}


本題的答案是:AABB

Virtual是C++ OO機制中很重要的一個關鍵字。只要是學過C++的人都知道在類Base中加了Virtual關鍵字的函式就是虛擬函式(例如函式print),於是在Base的派生類Derived中就可以通過重寫虛擬函式來實現對基類虛擬函式的覆蓋。當基類Base的指標point指向派生類Derived的物件時,對point的print函式的呼叫實際上是呼叫了Derived的print函式而不是Base的print函式。這是物件導向中的多型性的體現。(關於虛擬機器制是如何實現的,參見Inside the C++ Object Model ,Addison Wesley 1996)
class Base
{
public:Base(){}
public:
       virtual void print(){cout<<"Base";}
};
 
class Derived:public Base
{
public:Derived(){}
public:
       void print(){cout<<"Derived";}
};
 
int main()
{
       Base *point=new Derived();
       point->print();
}

Output:
Derived
這也許會使人聯想到函式的過載,但稍加對比就會發現兩者是完全不同的:
(1)       過載的幾個函式必須在同一個類中;
覆蓋的函式必須在有繼承關係的不同的類中
(2)       覆蓋的幾個函式必須函式名、引數、返回值都相同;
過載的函式必須函式名相同,引數不同。引數不同的目的就是為了在函式呼叫的時候編譯器能夠通過引數來判斷程式是在呼叫的哪個函式。這也就很自然地解釋了為什麼函式不能通過返回值不同來過載,因為程式在呼叫函式時很有可能不關心返回值,編譯器就無法從程式碼中看出程式在呼叫的是哪個函式了。
(3)       覆蓋的函式前必須加關鍵字Virtual;
過載和Virtual沒有任何瓜葛,加不加都不影響過載的運作。

 

相關文章