莎士比亞有一個關(guān)于名字的說法。"What’s in a name?" 他問道,"A rose by any other name would smell as sweet."(語出《羅密歐與朱麗葉》第二幕第二場,朱生豪先生譯為:“姓名本來是沒有意義的;我們叫做玫瑰的這一種花,要是換了個名字,他的香味還是同樣的芬芳?!绷簩?shí)秋先生譯為:“姓算什么?我們所謂有玫瑰,換個名字,還是一樣的香?!薄g者注)。莎翁也寫過 "he that filches from me my good name ... makes me poor indeed."(語出《奧塞羅》第三幕第三場,朱生豪先生譯為:“可是誰偷去了我的名譽(yù),那么他雖然并不因此而富足,我卻因?yàn)槭ニ蔀槌嘭毩??!绷簩?shí)秋先生譯為:“但是他若奪去我的名譽(yù),于他不見有利,對我卻是一件損失哩?!薄g者注)。好吧,在 C++ 中,我們該用哪種態(tài)度對待通過繼承得到的名字呢?
事情的實(shí)質(zhì)與繼承沒什么關(guān)系。它與作用域有關(guān)。我們都知道它在代碼中是這樣的,
int x; // global variable
void someFunc()
{
double x; // local variable
std::cin >> x; // read a new value for local x
}
讀入 x 的語句指涉 local 變量 x,而不是 global 變量 x,因?yàn)閮?nèi)層作用域的名字覆蓋(“遮蔽”)外層作用域的名字。我們可以像這樣形象地表示作用域的狀況:
當(dāng)編譯器在 someFunc 的作用域中遇到名字 x 時,他們巡視 local 作用域看看是否有什么東西叫這個名字。因?yàn)槟抢镉?,它們就不再檢查其它作用域。在此例中,someFunc 的 x 類型為 double,而 global x 類型為 int,但這不要緊。C++ 的 name-hiding 規(guī)則僅僅是覆蓋那個名字。而相對應(yīng)的名字的類型是否相同是無關(guān)緊要的。在此例中,一個名為 x 的 double 覆蓋了一個名為 x 的 int。
加入 inheritance 以后。我們知道當(dāng)我們在一個 derived class member function 內(nèi)指涉位于 base class 內(nèi)的一件東西(例如,一個 member function,一個 typedef,或者一個 data member)時,編譯器能夠找到我們指涉的東西是因?yàn)?derived classes 繼承到聲明于 base classes 中的東西。實(shí)際中的運(yùn)作方法是將 derived class 的作用域嵌套在 base class 作用域之中。例如:
class Base {
private:
int x;
public:
virtual void mf1() = 0;
virtual void mf2();
void mf3();
...
};
class Derived: public Base {
public:
virtual void mf1();
void mf4();
...
};
本例中包含的既有 public 名字也有 private 名字,既有 data members 也有 member functions。member functions 既有 pure virtual 的,也有 simple (impure) virtual 的,還有 non-virtual 的。那是為了強(qiáng)調(diào)我們談?wù)摰氖虑槭顷P(guān)于名字的。例子中還可以包括其它類型的名字,例如,enums,nested classes,和 typedefs。在這里的討論中重要的事情是“它們是名字”。與它們是什么東西的名字毫不相關(guān)。這個示例中使用了 single inheritance,但是一旦你理解了在 single inheritance 下會發(fā)生什么,C++ 在 multiple inheritance 下的行為就很容易預(yù)見了。
事情的實(shí)質(zhì)與繼承沒什么關(guān)系。它與作用域有關(guān)。我們都知道它在代碼中是這樣的,
int x; // global variable
void someFunc()
{
double x; // local variable
std::cin >> x; // read a new value for local x
}
讀入 x 的語句指涉 local 變量 x,而不是 global 變量 x,因?yàn)閮?nèi)層作用域的名字覆蓋(“遮蔽”)外層作用域的名字。我們可以像這樣形象地表示作用域的狀況:
當(dāng)編譯器在 someFunc 的作用域中遇到名字 x 時,他們巡視 local 作用域看看是否有什么東西叫這個名字。因?yàn)槟抢镉?,它們就不再檢查其它作用域。在此例中,someFunc 的 x 類型為 double,而 global x 類型為 int,但這不要緊。C++ 的 name-hiding 規(guī)則僅僅是覆蓋那個名字。而相對應(yīng)的名字的類型是否相同是無關(guān)緊要的。在此例中,一個名為 x 的 double 覆蓋了一個名為 x 的 int。
加入 inheritance 以后。我們知道當(dāng)我們在一個 derived class member function 內(nèi)指涉位于 base class 內(nèi)的一件東西(例如,一個 member function,一個 typedef,或者一個 data member)時,編譯器能夠找到我們指涉的東西是因?yàn)?derived classes 繼承到聲明于 base classes 中的東西。實(shí)際中的運(yùn)作方法是將 derived class 的作用域嵌套在 base class 作用域之中。例如:
class Base {
private:
int x;
public:
virtual void mf1() = 0;
virtual void mf2();
void mf3();
...
};
class Derived: public Base {
public:
virtual void mf1();
void mf4();
...
};
本例中包含的既有 public 名字也有 private 名字,既有 data members 也有 member functions。member functions 既有 pure virtual 的,也有 simple (impure) virtual 的,還有 non-virtual 的。那是為了強(qiáng)調(diào)我們談?wù)摰氖虑槭顷P(guān)于名字的。例子中還可以包括其它類型的名字,例如,enums,nested classes,和 typedefs。在這里的討論中重要的事情是“它們是名字”。與它們是什么東西的名字毫不相關(guān)。這個示例中使用了 single inheritance,但是一旦你理解了在 single inheritance 下會發(fā)生什么,C++ 在 multiple inheritance 下的行為就很容易預(yù)見了。