2013年8月28日 星期三

C++ 的 C style cast 不等於 static_cast

即使看了幾次《Effective C++》item 27 "Minimize casting", 還是不明白 C style cast 有什麼重大問題。只覺得新的 cast 比較明確安全, 但寫起來很囉唆, 又是角括號又是括號 (愛惜手指, 請從少按 shift 做起)。一直以為 C style cast 等同於 static_cast, 這樣的話, 在使用 static_cast 的場合, 就偷懶寫成 C style cast 吧。

今天看到 Ken 寫的 On C-Style Cast in C++, 才發覺情況和我想得不同。於是寫個小程式驗證一下:

$ cat b.cpp -n
     1  class A {};
     2  class B : public A {};
     3  class C {};
     4
     5  int main(void) {
     6    A* a = new A();
     7    B* b = (B*)a;
     8    C* c = (C*)a;
     9    B* b2 = static_cast<B*>(a);
    10    C* c2 = static_cast<C*>(a);
    11    return 0;
    12  }
$ g++ b.cpp -o b
b.cpp: In function ‘int main()’:
b.cpp:10:28: error: invalid static_cast from type ‘A*’ to type ‘C*’

果真 C style cast 可以隨意轉換, static_cast 限制較為嚴格一些, 但是 pointer-to-base 仍可透過 static_cast 轉成 pointer-to-derived (即使轉型後會有問題)。若需要更安全的作法, 可以用 dynamic_cast, 看轉完的值是否為空指標, 可以知道是否能安全轉過去。代價是會增加執行時間, 詳細說明見《Effective C++》item 27 "Minimize casting"。關於轉型最重要的觀念, 大概就是盡量別轉型吧。

沒有留言:

張貼留言

在 Fedora 下裝 id-utils

Fedora 似乎因為執行檔撞名,而沒有提供 id-utils 的套件 ,但這是使用 gj 的必要套件,只好自己編。從官網抓好 tarball ,解開來編譯 (./configure && make)就是了。 但編譯後會遇到錯誤: ./stdio.h:10...