繼承與遮掩問題
繼承:
pure virtual 函數的目的是為了讓Derived class 只繼承函數接口。
impure virtual(虛) 函數的目的是讓Derived class 繼承該函數的接口和缺省實現。
non-virtual(普通) 函數的目的是為了令Derived class 繼承函數的接口及一份強制性實現。如果成員函數是個non-virtual函數,意味著它並不打算在Derived class中有不同的行為。
遮掩:
以作用域為基礎的“名稱遮掩規則”同樣適用於類的繼承。而且不論函數是virtual或non-virtual都一體適用。
事例:
Derived class 內的名稱會遮掩 Base class 內的名稱。
class Base
{
private:
int x;
public:
virtual void mf1() = 0;
virtual void mf1(int);
virtual void mf2();
void mf3();
void mf3(double);
};
class Derived: public Base
{
public:
virtual void mf1();
void mf3();
void mf4();
};
Derived d;
int x;
d.mf1(); //沒問題,調用Derived::mf1;
d.mf1(x); //錯誤,因為Derived::mf1遮掩了Base::mf1
d.mf2(); //沒問題,調用Base::mf2
d.mf3(); //沒問題,調用Derived::mf3
d.mf3(x) //錯誤,因為Derived::mf3遮掩了Base::mf3
為了讓遮掩的名稱再見天日,可使用using 聲明式或轉交函數。
事例:
使用using聲明式解決遮掩問題。
class Derived: public Base
{
public:
using Base::mf1; //讓Base class 內名為mf1和mf3的所有東西
using Base::mf3; //在Derived 作用域內都可見。
virtual void mf1();
void mf3();
void mf4();
};
Derived d;
int x;
d.mf1(); //沒問題,調用Derived::mf1;
d.mf1(x); //現在沒問題了,調用Base::mf1
d.mf2(); //沒問題,調用Base::mf2
d.mf3(); //沒問題,調用Derived::mf3
d.mf3(x) //現在沒問題了,調用Base::mf3
使用 using 聲明還可以做到在Derived類中重載Base類中的函數(別忘了,原來意義的重載只可以重載當前類中的函數)。