繼承情況下的類作用域

2021-06-06 05:42:24 字數 4618 閱讀 6873

建構函式和析構函式中的虛函式,構造和析構也是分階段的,也就是說從無到基類物件,再到派生類物件,從派生類物件到基類物件,再到無。

這中間有乙個狀態就是基類物件,此時直接或間接呼叫虛函式,只能是基類中的版本,因為後邊的還沒形成呢。

因為如果使用派生類中的版本,可能需要訪問派生類物件的成員,而這些還不存在,為了避免這個崩潰風險,就給遮蔽了。

繼承情況的類作用域:

派生類的作用域巢狀在基類作用域中,如果不能在派生類作用域中確定名字,就在外圍基類作用域中查詢該名字的定義。

靜態型別的優先權

在item_base和bulk_item中間的disc_item中加一函式,靜態繫結吧。。。靜態繫結是編譯時而非執行時,也就是說編譯時查名字discount_policy()位置

利用指標和引用來找是動態的此例沒虛函式,這樣bulk_item先找自己,根據作用域巢狀,再找直接基類disc_item,而如果指標是基類型別的,因為根本沒宣告,找不到discount_policy()函式。

class disc_item : public item_base 

};

bulk_item *bulkp = &bulk;	//ok:static and dynamic types are the same

item_base *itemp = &bulk; //ok:static and dynamic types differ

bulkp->discount_policy(); //ok:bulkp has type bulk_item*

itemp->discount_policy(); //error:itemp has type item_base*

名字衝突與繼承:

基本也沒什麼東西,不過就是作用域操作符

int get_mem() 			//returns derived::mem

int get_base_mem() //returns base::mem

規律是這麼個規律,不過也是要盡量避免的,不出現最好

就和那句典型的setdata()一樣

不一樣的是那個是函式體內形參覆蓋類中成員,這裡是派生類成員覆蓋同名的基類成員

pe23_2.cpp  原題的關於基類和派生類的定義錯誤太多,這是改版

比較奇特的發現:第乙個,基類的foo_bar和派生類的foo_bar()沒有名字衝突,而基類的bar和派生類的bar(base *pb)衝突

第二個,不光有基類派生類的名字衝突問題,解決了名字遮蔽問題,還要遇到派生類不能訪問基類protected成員問題

//原題有問題,修改

#includestruct base ;

struct derived : public base ;

//第二題,錯誤一樣,試圖給base::bar賦值1024,其實被遮蔽了,結果是bar認為1024是個不恰當的字串初始位址,提示是不是缺&

//void derived::foo_bar()

//第三題,似乎沒錯,除非題目的定義錯了,原意是不是派生類的方法foo_bar()遮蔽基類的foo_bar,

//實際上基類的成員和派生類的成員函式同名也不允許啊。。。。。。

//其實還有問題,基類是protected,直接訪問不成靜態繫結也不成~!!!!!!!!!!!!!!!!

//bool derived::bar(base *pb)

//

int main()

作用域與成員函式:

derivedoverload.cpp

小結:和區域性函式不會過載全域性函式一樣,只要函式名相同,引數列表無所謂,派生類重定義的覆蓋作用大於過載功能,正常情況下派生類要麼不過載基類成員,要麼全覆蓋掉

用using 宣告,可以引入基類成員(相當於都複製過來一遍),引入後就相當於在派生類作用域內展開過載了

//基類和派生類的成員函式不能過載,是覆蓋,在派生類重定義成員函式的前提下,即使引數不對,直接找不到,也不會去基類找的,

//不過也可以用base::直接呼叫基類成員

//當然,使用using base::memfcn引入基類成員,就可以過載了。。

#includestruct base

};struct derived : base //hides memfcn in the base

};int main()

虛函式與作用域:

review:動態繫結的前提條件--通過指標或引用呼叫虛成員。

當我們這樣做時,編譯器將在基類中查詢函式(怎麼沒說後續去派生類找啊~)。假定找到了名字,編譯器就檢查實參是否與形參匹配。

這就可以理解為什麼虛函式要求基類和派生類中有同一原型

如果實參不同,就沒有辦法通過基類型別的ptr和ref呼叫派生類函式,文字不太好理解,看看code。

也就是說ptr和ref意味著動態繫結,動態繫結要帶著引數一塊呼叫的,如果引數不匹配,base*是不在乎derived中有什麼的。

/*virtualandscope.cpp*/

//虛函式與作用域,示例--重點在d2,d2中既有虛函式,又有重定義覆蓋。。。

#includeclass base

};class d1 : public base //parameter list differs from fcn in base

//d1 inherits definition of base::fcn()

//引數列表不匹配不算虛函式。雖然繼承base::fcn(),但是d1::fcn()還是沒有的

};class d2 : public d1 //nonvirtual function hides d1::fcn(int)

int fcn() //redefines virtual fcn from base

};int main()

小改版,base中取消virtual,d1加virtual,base和d1過載,d1和d2虛函式繫結,然後動態呼叫

using base::fcn;

virtual int d1::fcn(int)

d1 *dp2 = &d1obj, *dp3 = &d2obj;

dp2->fcn();

dp2->base::fcn();

dp2->fcn(2);

dp3->fcn();

dp3->base::fcn();

dp3->fcn(2);

關鍵概念:名字查詢與繼承

理解c++繼承層次的關鍵在於理解如何確定函式呼叫,確定函式呼叫遵循以下4個步驟

在譯本p501(原版594)頁尾。。。

習題15.24

//習題,懶得實現了,簡單問題,乙個是經過複製構造,複製出了item_base物件,乙個是動態的,識別出是bulk_item物件,用virtual

pe15_25.cpp  有點小困惑,過載好像不關心返回型別著,但是虛函式呢。

另外,前邊能正常執行的,後來連derived d;都不允許了,提示很詭異。我又沒呼叫copy(),必須先完成定義麼?是說copy()很特殊

。。(mark)

//四小題,base中的虛函式,加入derived打算定義自己的這個虛函式版本,確定哪個宣告是錯誤的

#includeclass base     //d)

};class derived : public base                 //d)沒錯,const不影響虛函式

};int main()

錯誤提示

g++ -wall -o "pe15_25" "pe15_25.cpp" (in directory: /home/huqinwei/cppworkspace/chap15)

/tmp/ccl8gimw.o: in function `base::base()':

pe15_25.cpp:(.text._zn4basec2ev[_zn4basec5ev]+0x8): undefined reference to `vtable for base'

/tmp/ccl8gimw.o:(.rodata._ztv7derived[vtable for derived]+0x8): undefined reference to `base::copy(base*)'

/tmp/ccl8gimw.o:(.rodata._zti7derived[typeinfo for derived]+0x8): undefined reference to `typeinfo for base'

collect2: ld returned 1 exit status

compilation failed.

繼承情況下類的作用域

在繼承情況下,派生類的作用域巢狀在基類作用域中。因此,如果不能在派生類作用域中確定的名字,就在外圍基類作用域中查詢該名字的定義。在基類和派生類中使用同一名字的成員函式,其行為與資料成員一樣 在派生類作用域中派生類成員將遮蔽基類成員。即使函式原型不同,基類成員也會被遮蔽。如果要訪問被遮蔽的基類成員,需...

C 中繼承情況下的類作用域

首先,每乙個類都保持著自己的作用域,在該作用域中定義了成員的名字。物件 引用或指標的靜態型別決定了物件能夠完成的行為 c primer 這裡能夠完成的行為,應該說是能夠使用的變數名 資料和方法 這些變數名是定義在呼叫它的物件 引用或指標的靜態型別中的。為什麼將行為改為變數名,是因為我覺得行為是處理事...

Java 繼承情況下例項變數的初始化

package scjp class x class y public class demo65 extends x public static void main string args 執行結果 yxyz 分析 1.new demo65 1.2.demo65的超類是x,所以 new x 1.2....