C++物件模型之七 模板 異常 RTTI筆記 (轉)

amyz發表於2007-11-13
C++物件模型之七 模板 異常 RTTI筆記 (轉)[@more@] 

C++模型之七 模板 異常 RTTI筆記:namespace prefix = o ns = "urn:schemas--com::office" />

下面關於模板的三個問題:

1 模板的宣告時會發生什麼

2 如何例項化出類物件內聯成員

3 如何例項化出成員,模板成員,模板靜態成員.

Template

Class point

{

 public:

  enum Status { unallocated, normalized };

 point (T x=0.0,T y=0.0, T z=0.0);

 ~point ();

void * operator new ( size_t );

void * opertaor deleted (vo * , size_t );

private:

 static point * freeList;

 static int ChunSize;

 T _x, _y, _z;

};

當看到template class 宣告時,它什麼反應也沒有,上述的靜態資料成員,巢狀列舉 不可用. 雖然enum status 的真正的型別在所有的point例項中都一樣.但是它們必須透過模板point類的例項來存取和操作.

Point :: Status S; // OK

Point ::Status S;//Error

指標: const point < float > * ptr = 0;  不會例項化;

引用: const point < float > & ref = 0; 會例項化

è point < float > temp ( floa t (0 ) ); const point < float > & ref = temp;

 

模板的錯誤報告: 所有的語法錯誤被檢測出來,但不做型別檢查.

 

模板中的名稱解決方式

extern double foo ( double ); //類S的定義

template < class T>

class S

{

 public:

  void invariant () { member = foo ( val); }

  T dependent() { return foo ( member) ;}

 private:

  int val;

  T member;

};

extren int foo (int );

S S1;

S1.invariant();

S1.dependent();

模板中對於成員名稱的解決結果時根據這個名稱的使用是否與”用以例項化出該模板的引數型別有關” 而決定.沒有關就採用類的定義來解決, 有關就採用例項化的引數型別.

因此: S1.invariant();中的foo 的 extern double foo ( double ); 因為void invariant () { member = foo ( val); }中的val 是int val; 型別無關.而 S1.dependent(); 中的foo 呼叫的 extern int foo ( int  );因為T dependent() { return foo ( member) ;}中的member 是T member; 型別有關.

成員函式的例項化

只有在成員函式使用時後C++標準才要它們被例項化出來.但是並不精確遵循.願意如下:

1 空間和時間的考慮. 如果類中有100個成員函式,但你的只針對某個型別的7個函式,那麼其他的193個函式都要被例項化將花費大量的時間和空間.

2 尚未實現的機制,並不是一個模板例項化出來的所有型別就一定能夠完整支援一組成員函式所需的所有運算子.

Point < float > *ptr = new point < float >;

用到了 void * operator new ( size_t );  point (T x=0.0,T y=0.0, T z=0.0);

目前編譯器有兩個策略: 1是編譯時期程式程式碼必須在程式文字中備妥當,2 是連線時用工具引導編譯器例項化行為.

1 編譯器如何找出函式的定義?

  1是包含在模板程式文字中,2 要求一個檔案命名規則.

2 編譯器如何只例項化程式中用到的成員函式?

 1 根本忽略,把一個已經例項化的類所有的成員函式都生產出來. 2模擬連線操作: 檢測哪個函式真正需要.

3 編譯器如何阻止成員定義在多個obj檔案中都被例項化?

1 產生多個例項在連線時候只留下一個. 2 由使用者來引導”模擬連線階段”的例項.

Borland 支援所有問題的第一中方法.

異常處理

一般而言異常處理機制需要與編譯器所產生的資料結構以及期的一個異常庫精密合作.

編譯器在程式速度和大小方面做出選擇

1 為了維持執行速度,編譯器可以在編譯時期建立起用於的資料結構.但編譯器可以忽略這些結構直到異常

2 為了維護程式大小,編譯器可以在執行期建立起用於的資料結構, 但編譯器只有在必要的時候才建立資料結構.

異常可以不程式劃分為多個區域: try block 以外 和try block以內以及整個區域.

void mumble ( void * arena )

{

 point *p = new point ;

 try

{

smlock ( arena );

}

catch (…)

{

smunlock ( arena );

delete p;

throw ;

}

smunlock (arena);

delete p;

}

為什麼  point *p = new point ;不在try block以內? 因為它之前沒有什麼要釋放的東西.雖然它自己也會丟擲異常,但是它會自己處理調資源釋放的問題.

支援異常會使成員物件或基類子物件的類的建構函式複雜化. 比如: 類X有成員物件 A,B,C.它們都有一對的構造和解構函式. 但A的建構函式丟擲異常,那麼A,B,C的析構不用呼叫. 但 B的建構函式丟擲異常,那麼A的析構要呼叫,C的析構不用呼叫. 一樣的是 point3d *ptr = new point3d [512]; 假如第100個元素丟擲異常,那麼前99個要呼叫析構,後面的就不用呼叫.

當一個異常發生時,編譯器要完成以下事情:

1 檢驗throw 操作函式

2 決定 throw 操作是否發生在try 區域中

 2.1 如果是 編譯器把異常型別和每一個catch比較

 2.2 如果比較吻合,流程控制權交到catch中

3 如果 throw 操作不發生在try 區域中 或者沒有一個catch吻合 那麼會做 1 釋放所有本地存在的物件, 2 從堆疊中將當前的函式展開掉 3 進行到程式堆疊中的下一個函式,然後重複2-3

 

決定 throw 操作是否發生在try 區域中 函式中會生成區域統計表

如果是 編譯器把異常型別和每一個catch比較 系統會採用型別描述器(RTTI)

當異常被丟出時,異常物件會放在相同形式的異常資料堆疊中,從throw傳給catch 的是 異常物件地址和型別描述器.一般catch( ex &p) 基本上採用引用 如果是物件,有能發生切割.

物件大小

沒有異常

有異常

百分比

Borland

86.822

89.510

3%

Microsoft

60.146

67.071

13%

69.786

74.826

8%

執行速度

 

Borland

78

83

6%

Microsoft

83

87

5%

Symantec

94

96

4%

執行期型別識別(RTTI)

向下相容:

RTTI是後來引進的,並沒有使用新的關鍵字,而是如果宣告的虛擬函式就會有RTTI。

動態型別轉換:dynamic_cast可以在執行期決定型別,如果成功將傳回指標否則是0 比靜態轉換成本要貴的多,但是也多了。Dynamic_cast < Type > ( &pt)  如果是引用失敗後返回的是bad_cast異常。

TYPEID:

 使用它可以同樣達到引用的目的

 if ( typeid (rt)== typeid (fct))

 fct &rf=static_cast(rf);

typeid 轉會來的const 引用 型別為type_info : bool type_info ::operator==(const type_info&) cosnt;

class type_info

{

 public:

 virtual ~type_info();

 bool  operator==(const type_info&) const;

 bool  operator!=(const type_info&) const;

bool before (const type_info &) const;

const char *name() const;

private:

 type_info (const type_infor&);

 type_info & operator = (const type_info &);

};

RTTI 適合與多型 type 適合於普通類和一般型別。

曾牧暗鯊 && 大白鯊 -8-19

 


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-982204/,如需轉載,請註明出處,否則將追究法律責任。

相關文章