C++ overload、override、overwrite
對於函式的過載(overload)、覆蓋(override)、重寫(overwrite)三者的理解,通過程式碼來分析。
過載:是指同一可訪問區內被宣告的幾個具有不同引數列(引數的型別,個數,順序不同)的同名函式,根據引數列表確定呼叫哪個函式,過載解析中不考慮返回型別,而且在不同的作用域裡宣告的函式也不算是過載。
class A{
public:
void func(int i);
void func(double i);//overload
void func(int i, double j);//overload
void func(double i, int j);//overload
int func(int i); //非過載。注意過載考慮函式返回型別。
};
覆蓋:是指派生類中存在重新定義的函式。其函式名,引數列表,返回值型別,所有都必須同基類中被重寫的函式一致。只有函式體不同(花括號內),派生類呼叫時會呼叫派生類的重寫函式,不會呼叫被重寫函式。重寫的基類中被重寫的函式必須有virtual修飾。
#include<iostream>
using namespace std;
class Base
{
public:
virtual void fun(int i){ cout << "Base::fun(int) : " << i << endl;}
};
class Derived : public Base
{
public:
virtual void fun(int i){ cout << "Derived::fun(int) : " << i << endl;}
};
int main()
{
Base b;
Base * pb = new Derived(); //向上造型
pb->fun(3); //Derived::fun(int)
delete pb;
system("pause" );
return 0;
}
重寫
是指派生類的函式遮蔽了與其同名的基類函式,規則如下:
(1)如果派生類的函式與基類的函式同名,但是引數不同。此時,不論有無virtual關鍵字,基類的函式將被隱藏。
(2)如果派生類的函式與基類的函式同名,並且引數也相同,但是基類函式沒有virtual關鍵字。此時,基類的函式被隱藏(注意別與覆蓋混淆)。
class Base{
public:
virtual int fcn();
};
class D1:public Base{
public:
//隱藏基類的fcn,這個fcn不是虛擬函式
//D1繼承了Base::fcn()的定義
int fcn(int); //形參類別與Base中的fcn不一樣
virtual void f2(); //是一個新的虛擬函式,在Base中不存在
};
class D2:public D1{
public:
int fcn(int); //是一個非虛擬函式,隱藏了D1::fcn(int)
int fcn(); //覆蓋了Base的虛擬函式fcn
void f2(); //覆蓋了D1的虛擬函式f2
D1的fcn函式並沒有覆蓋Base的虛擬函式fcn,原因是他們的形參列表不同。實際上,D1的fcn將隱藏Base的fcn。此時擁有了兩個名為fcn的函式,一個D1從Base繼承而來的虛擬函式fcn,另一個是D1自己定義的接收一個int引數的非虛擬函式fcn。
下面寫一個例子,可以通過定義基類是否有virtual關鍵字來幫助判斷。
// test.cpp : 定義控制檯應用程式的入口點。
#include "stdafx.h"
#include <iostream>
using namespace std;
class A {
public:
A() {}
void print(int x); //定義函式
void print(int x, int y);
void print();
~A() {}
};
void A::print(int x)
{
cout << "A::print(int x)" << endl;
}
void A::print(int x, int y)
{
cout << "A::print(int x,int y)" << endl;
}
void A::print()
{
cout << "A::print()" << endl;
}
class B :public A {
public:
B() {}
void print(int x);
~B() {}
};
int main()
{
A a;
B b;
a.print(1);
a.print(1,2);
b.print(1);
b.print(1,2); //錯誤,函式不接受2個引數
return 0;
}
在上面的b.print(1,2)
中提示錯誤,其實是如果基類定義了overloaded(過載)函式,那麼在子類必須override(覆蓋)所有你所定義的overloaded(過載)函式,不能只override一個,如果沒有override所有過載函式,那麼沒有被override的將會被隱藏,只能父類呼叫,不能子類呼叫。