C++中成員函式的過載、覆蓋與隱藏
阿新 • • 發佈:2018-12-03
成員函式被過載的特徵:
(1)相同的範圍(在同一個類中);
(2)函式名字相同;
(3)引數不同;
(4)virtual關鍵字可有可無。
覆蓋是指派生類函式覆蓋基類函式,特徵是:
(1)不同的範圍(分別位於派生類與基類);
(2)函式名字相同;
(3)引數相同;
(4)基類函式必須有virtual關鍵字。
隱藏是指派生類的函式遮蔽了與其同名的基類函式,規則如下:
(1)如果派生類的函式與基類的函式同名,但是引數不同。此時,不論有無virtual關鍵字,基類的函式將被隱藏(注意別與過載混淆)。
(2)如果派生類的函式與基類的函式同名,並且引數也相同,但是基類函式沒有virtual關鍵字。此時,基類的函式被隱藏(注意別與覆蓋混淆)。
例:
#include <iostream.h> class Base { public: virtual void f(float x){ cout << "Base::f(float) " << x << endl; } void g(float x){ cout << "Base::g(float) " << x << endl; } void h(float x){ cout << "Base::h(float) " << x << endl; } }; class Derived : public Base { public: virtual void f(float x){ cout << "Derived::f(float) " << x << endl; } void g(int x){ cout << "Derived::g(int) " << x << endl; } void h(float x){ cout << "Derived::h(float) " << x << endl; } }; void main(void) { Derived d; Base *pb = &d; Derived *pd = &d; pb->f(3.14f); pd->f(3.14f); pb->g(3.14f); pd->g(3.14f); pb->h(3.14f); pd->h(3.14f); } /* 注意: (1)函式Derived::f(float)覆蓋了Base::f(float)。 (2)函式Derived::g(int)隱藏了Base::g(float),而不是過載。 (3)函式Derived::h(float)隱藏了Base::h(float),而不是覆蓋。 */
執行結果:
Derived::f(float) 3.14
Derived::f(float) 3.14
Base::g(float) 3.14
Derived::g(int) 3
Base::h(float) 3.14
Derived::h(float) 3.14
再看下面這個例子:
class Base { public: void f(int x); }; class Derived : public Base { public: void f(char *str); }; void Test(void) { Derived *pd = new Derived; pd->f(10); // 出錯 }
隱藏規則至少有兩個存在的理由:
1.寫語句pd->f(10)的人可能真的想呼叫Derived::f(char *)函式,只是他誤將引數寫錯了。有了隱藏規則,編譯器就可以明確指出錯誤。否則,編譯器會靜悄悄地將錯就錯,程式設計師將很難發現這個錯誤,留下禍根。
2.假如類Derived有多個基類(多重繼承),有時搞不清楚哪些基類定義了函式f。如果沒有隱藏規則,那麼pd->f(10)可能會呼叫一個出乎意料的基類函式f。儘管隱藏規則看起來不怎麼有道理,但它的確能消滅這些意外。
將程式進行如下修改就正確了
class Base
{
public:
void f(int x);
};
class Derived1 : public Base
{
public:
void f(char *str);
void f(int x) { Base::f(x); }
};
void Test1(void)
{
Derived1 *pd = new Derived1;
pd->f(10); // 正確
}