《深度探索C++物件模型》讀書筆記(7)

來源:互聯網
上載者:User
《深度探索C++物件模型》讀書筆記(7)。

  ***Template的“具現”行為***

   template class中的任何member都只能通過template class的某個實體來存取或操作。

 Point<float>::Status s;  // ok
Point::Status s;  // error

   如果我們定義一個指標,指向特定的實體,像這樣:

 Point<float> *ptr = 0;

   由於這是一個指向class object的指標,本身並不是一個class object,編譯器不需要知道與該class有關的任何members資料。所以將“Point的一個float實體”具現也就沒有必要。

   如果不是一個pointer而是reference,假設:

 Point<float> &ref = 0;

   這個定義的真正語意會被擴充為:

 // 內部擴充
Point<float> temp(float(0));
Point<float> &ref = temp;

   以上轉化是因為reference並不是無物(no object)的代名詞,0被視作整數,必須被轉換為類型Point<float>的一個對象。

   然而,member functions只有在member functions被使用的時候,C++ Standard才要求它們被“具現”出來。這個規則的由來主要有兩個原因:

   (1)空間和效率的考慮。對於未使用的函數進行“具現”將會花費大量的時間和空間;

   (2)尚未實現的功能。並不是一個template具現出來的所有類型一定能夠完整支援一組member functions,因而只需具現真正需要的member functions.

   舉個例子:

 Point<float> *p = new Point<float>;

   只有(a)Point template的float執行個體、(b)new 運算子、(c)default constructor需要被“具現”。

關鍵字: malloc wxWidgets OpenGL 多態性 doxygen 《深度探索C++物件模型》讀書筆記(7)。

   ***Template的錯誤報表***

   所有與類型相關的檢驗,如果涉及到template參數,都必須延遲到真正的具現操作發生。

   對於下面的template聲明:

 template <class T>
class Mumble
{
public:
Mumble(T t = 1024) : _t(t)
{
if(tt != t)
throw ex ex;
}
private:
T tt;
}

   其中像“T t = 1024”、“tt != t”這樣的潛在錯誤在template聲明時並不會報告,而會在每個具現操作發生時被檢查出來並記錄之,其結果將因不同的實際類型而不同。

 Mumble<int> mi;  // 上述兩個潛在錯誤都不存在
Mumble<int*> pmi;  // 由於不能將一個非零的整數常量指定給一個指標,故“T t = 1024”錯誤

   ***Template中的名稱決議方式***

   區分以下兩種意義:一種是“scope of the template definition”,也就是“定義出template”的程式,另一種是“scope of the template instantiation”,也就是“具現出template”的程式。

 // scope of the template definition
extern double foo(double);

template <class type>
class ScopeRules
.{
public:
void invariant() { _member = foo(_val); }
type type_dependent() { return foo(_member); }
// ...
private:
int _val;
type _member;
};

// scope of the template instantiation
extern int foo(int);

ScopeRules<int> sr0;

關鍵字: malloc wxWidgets OpenGL 多態性 doxygen 《深度探索C++物件模型》讀書筆記(7)。

   在“scope of the template definition”中,只有一個foo()函式宣告位於scope之內;然而在“scope of the template instantiation”中,兩個foo()函式宣告都位於scope之內。對於以下函數操作:

 // scope of the template instantiation
sr0.invariant();

   那麼,在invariant()中調用的究竟是哪一個foo()函數實體呢?

   Template之中,對於一個nonmember name的決議結果是根據這個name的使用是否與“用以具現出該template的參數類型”有關而決定的,如果其使用互不相關,那麼就以“scope of the template definition”來決定name,否則就以“scope of the template instantiation”來決定name.

 // 因為_val的類型是int,而函數的決議只和函數原型有關,與函數傳回值無關
// 被用來具現這個template的真正類型對於_val的類型沒有影響
_member = foo(_val);

   故此處的叫用作業由“scope of the template definition”來決議。

   若是如下的函數調用:

   sr0.type_dependent();

   由於_member的類型與template參數有關,故此處由“scope of the template instantiation”來決議。

   ***Member Function的具現行為***

   以手動方式在個別的object module中完成預先具現操作,是唯一有效率的辦法。

   ***執行期類型識別***

   dynamic_cast運算子可以在執行期決定真正的類型。如果downcast是安全的(也就是說,一個base type pointer指向一個derived class object),這個運算子會傳回被適當轉型過的指標;如果downcast不是安全的,這個運算子會傳回0.

關鍵字: malloc wxWidgets OpenGL 多態性 doxygen 《深度探索C++物件模型》讀書筆記(7)。

 typedef type *ptype;
typedef fct *pfct;

simplify_conv_op(ptype pt)
{
if(pfct pf = dynamic_cast<pfct>(pt)) {
...
}
else { ... }
}

   什麼是dynamic_cast的真正成本?pfct的一個類型描述器會被編譯器產生出來,由pt指向之class object類型描述器必須在執行期通過vptr取得。下面是可能的轉換:

 // 取得pt的類型描述器
((type_info*)(pt->vptr[0]))->_type_description;

   其中,type_info是C++ Standard所定義的類型描述器的class名稱,該class中放置著待索求的類型資訊。virtual table的第一個slot內含type_info object的地址,此type_info object與pt所指之class type有關。

   dynamic_cast運算子也適用於reference身上,然而對於一個non-type-safe-cast,其結果不會與施行於指標的情況一樣。一個reference不可以像指標那樣“把自己設為0便代表了no object”;若將一個reference設為0,會引起一個臨時性對象(擁有被參考到的類型)被產生出來,該臨時對象的初值為0,這個reference然後被設定為該臨時變數的一個別名。

   因而,如果reference並不真正是某一種derived class,那麼可通過丟出一個bad_cast exception進行處理:

 simplify_conv_op(const type &rt)
{
try {
fct &rf = dynamic_cast<fct&>(rt);
}
catch(bad cast) {
// ...
}
}

   當然,你也可以使用typeid運算子來達到同樣的目的:

 simplify_conv_op(const type &rt)
{
if(typeid(rt) == typeid(fct))
{
fct &rf = dynamic_cast<fct&>(rt);
}
else { ... }
}

 

  系列文章:

  《深度探索C++物件模型》讀書筆記(1)

  《深度探索C++物件模型》讀書筆記(2)

  《深度探索C++物件模型》讀書筆記(3)

  《深度探索C++物件模型》讀書筆記(4)

  《深度探索C++物件模型》讀書筆記(5)

  《深度探索C++物件模型》讀書筆記(6)

  《深度探索C++物件模型》讀書筆記 最後一記

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.