C++物件模型之七 模板 異常 RTTI筆記 (轉)
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
static int ChunSize;
T _x, _y, _z;
};
當看到template class 宣告時,它什麼反應也沒有,上述的靜態資料成員,巢狀列舉 不可用. 雖然enum status 的真正的型別在所有的point例項中都一樣.但是它們必須透過模板point類的例項來存取和操作.
Point
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.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
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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- C++物件模型之六 執行期筆記 (轉)C++物件模型筆記
- C++筆記--異常C++筆記
- C++物件模型之五 構造 析構 賦值筆記 (轉)C++物件模型賦值筆記
- C++筆記--名字空間和異常C++筆記
- 《深度探索C++物件模型》讀書筆記C++物件模型筆記
- Java 筆記《異常》Java筆記
- 筆記:《七週七併發模型》筆記模型
- swoft 學習筆記之異常處理筆記
- Java學習筆記之自定義異常Java筆記
- c++異常處理 (轉)C++
- 筆記:異常處理之report與render筆記
- 深度解讀《深度探索C++物件模型》之C++物件的記憶體佈局C++物件模型記憶體
- C++筆記 14:審慎使用異常規格(exception specifications)C++筆記Exception
- Django筆記三十一之全域性異常處理Django筆記
- C++/C學習筆記(七)C++筆記
- java異常處理筆記Java筆記
- java學習筆記(異常)Java筆記
- 【筆記】forall 異常捕獲筆記
- C/C++學習筆記八(斷言與異常處理)C++筆記
- C++異常C++
- 《Mastering Delphi 6》學習筆記之七 (轉)AST筆記
- Docker筆記之七:RegistryDocker筆記
- Python 3 學習筆記之——錯誤和異常Python筆記
- 《C++ Primer》學習筆記(五):迴圈、分支、跳轉和異常處理語句C++筆記
- C++語言程式設計筆記 - 第12章 - 異常處理C++程式設計筆記
- C++ 物件模型C++物件模型
- C++物件模型C++物件模型
- 吳恩達大模型教程筆記-七-吳恩達大模型筆記
- C++程式設計思想筆記之四 (轉)C++程式設計筆記
- C++程式設計思想筆記之六 (轉)C++程式設計筆記
- C++異常安全C++
- OS筆記(中斷/異常機制)筆記
- 異常處理-PHP手冊筆記PHP筆記
- C與C++中的異常處理 (轉)C++
- Cris 的 Scala 筆記整理(七):物件導向筆記物件
- C++物件模型:objectC++物件模型Object
- C++學習筆記 — STL標準模板庫C++筆記
- 2.1.3 Python物件導向之異常處理Python物件