1. 程式人生 > >【C++拾遺】 C++函式過載、重寫、重定義的區別

【C++拾遺】 C++函式過載、重寫、重定義的區別

原創作品,轉載請標明http://blog.csdn.net/xiejingfa/article/details/48496593

函式過載(overload)
函式過載是指在一個類中宣告多個名稱相同但引數列表不同的函式,這些的引數可能個數或順序,型別不同,但是不能靠返回型別來判斷。特徵是:
(1)相同的範圍(在同一個作用域中);
(2)函式名字相同;
(3)引數不同;
(4)virtual 關鍵字可有可無(注:函式過載與有無virtual修飾無關);
(5)返回值可以不同;

函式重寫(也稱為覆蓋 override)
函式重寫是指子類重新定義基類的虛擬函式。特徵是:
(1)不在同一個作用域(分別位於派生類與基類);
(2)函式名字相同;
(3)引數相同;
(4)基類函式必須有 virtual 關鍵字,不能有 static 。
(5)返回值相同,否則報錯;
(6)重寫函式的訪問修飾符可以不同;

重定義(也稱隱藏)


(1)不在同一個作用域(分別位於派生類與基類) ;
(2)函式名字相同;
(3)返回值可以不同;
(4)引數不同。此時,不論有無 virtual 關鍵字,基類的函式將被隱藏(注意別與過載以及覆蓋混淆);
(5)引數相同,但是基類函式沒有 virtual關鍵字。此時,基類的函式被隱藏(注意別與覆蓋混淆);

例子

#include <iostream>
using namespace std;

class Base
{
public:
	// =========================================================================
	//  子類和父類返回值引數相同,函式名相同,有/無virtual關鍵字
	// =========================================================================
	
	//	若無virtual關鍵字,則在子類中宣告與父類同名的方法,從而覆蓋了父類的方法(函式重定義)
	void a() 
	{
		cout << "Base::a()" << endl;
	};

	// 若有virtual關鍵字,即為虛擬函式。由物件的型別決定呼叫哪個函式(多型,函式重寫override)。
	virtual void b()
	{
		cout << "Base::b()" << endl;
	}

	// =========================================================================
	//  子類和父類返回值引數不同,函式名相同,有/無virtual關鍵字 
	// =========================================================================

	// 若無virtual關鍵字,父類的同名成員被隱藏。
	void d(int x)
	{
		cout << "Base::d() x = " << x << endl;
	}

	// 若有virtual關鍵字,父類的同名成員同樣被隱藏。
	virtual void e(int x)
	{
		cout << "Base::e() x = " << x << endl;
	}

	// =========================================================================
	//  子類和父類返回值引數相同,函式名相同,函式返回值不同,有/無virtual關鍵字
	// =========================================================================

	// 若無virtual關鍵字(函式重寫,這種情況不屬於“函式過載”範疇)
	void f()
	{
		cout << "void Base::f()" << endl;
	}

	// 若有virtual關鍵字 (報錯)
	virtual void g()
	{
		cout << "virtual void Base::g()" << endl;
	}
};

class Derived : public Base
{
public:
	// =========================================================================
	//  子類和父類返回值引數相同,函式名相同,有/無virtual關鍵字
	// =========================================================================

	//	覆蓋了父類同名方法(函式重寫)
	void a() 
	{
		cout << "Derived::a()" << endl;
	}

	// 多型
	virtual void b()
	{
		cout << "Derived::b()" << endl;
	}

	// =========================================================================
	//  子類和父類返回值引數不同,函式名相同,有/無virtual關鍵字 
	// (注:函式過載與virtual關鍵字有無沒有關係)
	// =========================================================================

	// 父類同名成員被隱藏
	void d(int x, int y)
	{
		cout << "Derived::d() x = " << x << " y = " << y<< endl;
	}

	// 父類同名成員被隱藏
	virtual void e(int x, int y)
	{
		cout << "Derived::e() x = " << x << " y = " << y << endl;
	}

	// =========================================================================
	//  子類和父類返回值引數相同,函式名相同,函式返回值不同,有/無virtual關鍵字
	// =========================================================================

	// 返回值與基類不同
	int f()
	{
		cout << "int Derived::f()" << endl;
		return 1;
	}

	//// 錯誤
	//virtual int g()
	//{
	//	cout << "virtual int Base::g()" << endl;
	//	return 1;
	//}
};

int main()
{
	// 用作引數
	int xx = 100;

	cout << "子類和父類返回值引數相同,函式名相同,無virtual關鍵字" << endl;
	Derived d;
	d.a();		
	d.Base::a();	// 顯示呼叫基類方法
	cout << "子類和父類返回值引數相同,函式名相同,有virtual關鍵字" << endl;
	Base* b = new Derived;
	b->b();
	cout << "子類和父類返回值引數不同,函式名相同,無virtual關鍵字" << endl;
	d.d(xx, xx);
	// d.d(xx); // 報錯
	d.Base::d(xx); // 顯示呼叫
	cout << "子類和父類返回值引數不同,函式名相同,有virtual關鍵字" << endl;
	d.e(xx, xx);
	//d.e(xx); // 報錯
	d.Base::e(xx);
	cout << "子類和父類返回值引數相同,函式名相同,函式返回值不同, 無virtual關鍵字" << endl;
	d.f();
	d.Base::f();
}
輸出: