程式設計師面試寶典 RTTI與運算子過載

2021-07-05 04:50:20 字數 3908 閱讀 4767

❀rtti

rtti(run-time type identification)是物件導向程式設計中一種重要的技術。現行的c++標準對rtti已經有了明確的支援。不過在某些情況下出於特殊的開發需要,我們需要自己編碼來實現。和很多其他語言一樣,c++是一種靜態型別語言。其資料型別是在編譯期就確定的不能在執行時更改。然而由於物件導向程式設計中多型性的要求,c++中的指標或引用(reference)本身的型別,可能與它實際代表(指向或引用)的型別並不一致。有時我們需要將乙個多型指標轉換為其實際指向物件的型別,就需要知道執行時的型別資訊,這就產生了執行時型別識別的要求

c++提供了兩個關鍵字typeiddynamic_cast,乙個類type_info來支援rtti。

dynamic_cast操作符:它允許在執行時刻進行型別轉換,從而使程式能夠在乙個類層次結構安全地轉換型別。dynamic_cast提供了兩種轉換方式,把基類指標轉換成派生類指標,或者把指向基類的左值轉換成派生類的引用

void company::payroll(employee *pe)   

}

void company::payroll(employee &re)

catch(std::bad_cast)

}

這裡bonus是programmer的成員函式,基類employee不具備這個特性。所以我們必須使用安全的由基類到派生類型別轉換,識別出programmer指標。

動態對映dynamic_cast《目標*>《源指標》,先恢復源指標的rtti資訊,再取目標的rtti資訊,比較兩者是否相同,或者是目標型別的基類;由於它需要檢查一長串基類列表,故動態對映的開銷比typeid要大。

second *p2=dynamic_cast;//p是基類指標,把基類指標p通過這種方式變成其派生類的指標。

或者second *p2=

dynamic_cast;

typeid操作符:它指出指標或引用指向的物件的實際派生型別。

employee* pe=new manager;  

typeid(*pe)==typeid(manager) //true

typeid可以用於作用於各種型別名,物件和內建基本資料型別的例項、指標或者引用,當作用於指標和引用將返回它實際指向物件的型別資訊。typeid的返回是type_info型別。

type_info類

class type_info ;

執行型別識別rtti使用需要注意的問題

(1)在分布式系統中,不適用rtti的乙個合理的解釋是rtti行為不可預期及缺乏擴充套件性

(2)用typeid()返回乙個typeinfo物件,也可以用於內部型別,當用用於非多型型別時沒有虛函式,用typeid返回的將是基類位址;

(3)不能對void指標進行對映;

(4)如果p是指標,typeid(*p)返回p所指向的派生類型別,typeid(p)返回基類型別;如果r是引用,typeid(r)返回派生類型別,typeid(&r)返回基類型別;

(5)c++裡面的typeid運算子返回值是type_info常量物件的引用

❀運算子過載

所謂過載,就是重新賦予新的含義,函式過載就是對乙個已有的函式賦予新的含義,使之實現新功能。

運算子的過載主要存在兩種形式,一種是作為類的成員函式進行使用,另一種則是作為類的友元函式進行使用。

運算子的過載的形式:

返回型別 operator 運算子符號(引數說明)  

例如,能否用「+」號進行兩個複數的相加,在c++中不能在程式中直接用運算子「+」對複數進行相加運算,使用者必須自己設法實現複數相加。

運算子過載運算子的運算規則

(1)運算子過載函式也是函式,過載的運算子不會改變運算子的優先順序、結合型和引數的個數。

(2)過載運算子不能違反語言的語法規則。

(3)賦值運算子除外,過載運算子可由派生類繼承下去。

(4)過載運算子不能使用預設引數。

(5)運算子=、()、和->等操作符必須定義為類的成員函式,將這些操作符定義為友元函式將在編譯時標記為錯誤。

(6)c++中不能過載的運算子只有5個:

. (成員訪問運算子)

.* (成員指標訪問運算子)

∷ (域運算子)

sizeof(長度運算子)

?: (條件運算子)

因為前兩個運算子不能過載是為了保證訪問成員的功能不能被改變,域運算子和sizeof運算子的運算物件是型別而不是變數或一般表示式,不具過載的特徵。

(7)友元運算子的引數規則與類成員運算子的引數規則不同,一元運算子必須顯示地宣告乙個引數,二元運算子必須顯示地宣告兩個引數。類成員運算子過載時,引數中隱含了乙個this指標。(另外,c++規定,有的運算子(如賦值運算子、下標運算子、函式呼叫運算子)必須定義為類的成員函式,有的運算子則不能定義為類的成員函式(如流輸入「>>」和流輸出「<<」運算子、型別轉換運算子))。

過載為類的成員函式時,引數個數=原運算元個數-1(後置++、--除外),它可以通過this指標自由地訪問本類的資料成員,可以少寫乙個函式的引數,但必須要求運算表示式的第乙個引數(即運算子左側的運算元)是乙個類物件。

過載為類的友元函式時,引數個數 = 原運算元個數,且至少應該有乙個自定義型別的形參。

定義乙個過載運算子函式引數表中引數的決定個數,取決於兩個主要因素operator@

1)運算子是一元的(乙個引數)還是二元的(兩個引數)

2)運算子被定義為全域性函式:對於一元運算子,乙個引數;對於二元運算子是兩個引數

3)運算子是成員函式:對於一元運算子沒有引數,對於二元元素符是乙個引數

如何過載增量運算子++和--

運算子++和—-有前置和後置兩種形式,要使用operator++( )或operator--( )來過載前置運算子,使用operator++(int)或operator--(int)來過載後置運算子,呼叫時,引數int被傳遞給值0。

過載流輸入運算子和流輸出運算子

istream 類的物件cin;

ostream類的物件cout;

如果想直接用「<<」和「>>」輸出和輸入自己宣告的型別的資料,必須對它們過載,對「<<」和「>>」過載的函式形式如下:

istream & operator >> (istream &,自定義類 &);  

ostream & operator << (ostream &,自定義類 &);

過載運算子「>>」的函式的第乙個引數和函式的型別都必須是istream&型別,第二個引數是要進行輸入操作的類。

過載「<<」的函式的第乙個引數和函式的型別都必須是ostream&型別,第二個引數是要進行輸出操作的類。

只能將過載「>>」和「<<」的函式作為友元函式或普通的函式,而不能將它們定義為成員函式。

friend ostream & operator <<(ostream & out, const classm & a);//在類classm中宣告友元函式

ostream & operator <<(ostream & out, const classm & a)

//在類外寫函式體

呼叫:cout<

程式設計師面試寶典

據統計,80 的簡歷都是不合格的。不少人事管理者抱怨收到的許多簡歷在格式上很糟糕。簡歷應該如何做到在格式上簡潔明瞭,重點突出?求職信應該如何有足夠的內容推銷自己?如何控制長度,言簡意賅?相信讀了本章你會對簡歷的撰寫有乙個新的認識。2.1 簡歷注意事項 1 簡歷不要太長 一般的簡歷普遍都太長。其實簡歷...

黑馬程式設計師 運算子

運算子的基本概念 運算子是告訴編譯程式執行特定算數或邏輯操作的符號。運算子的分類 按照功能劃分 算術運算子 關係運算子 邏輯運算子 按位運算子。運算子根據參與運算的運算元的個數分為 單目運算,雙目運算 和三目運算子。單目運算子 只有乙個運算元.如 i sizeof 雙目運算子 有兩個運算元 如 a ...

黑馬程式設計師 運算子與陣列

asp.net android io開發s net培訓 期待與您交流!運算子 1 算術運算子 常見的幾種算數運算子 取餘數,取模 顧名思義這些運算子就是我們數學中常見的 加 減 乘 除和取餘 運算。乙個小小的簡單案例 2 復合運算子 常見的幾種 符合運算子 注 a 9 a a 9 其餘的都一樣運算 ...