C++ 學習 (static_cast、 volatile 等)

volatile ,變量修飾符,用於表示此變量是變化的,存取值時,會從內存直接讀取,而不進行優化。
注意:
(1) 可以把一個非 volatile int 賦給 volatile int,但是不能把非 volatile 對象賦給一個 volatile 對象。
(2) 除了基本類型外,對用戶定義類型也可以用 volatile 類型進行修飾。
(3) C++ 中一個有 volatile 標識符的類只能訪問它接口的子集,一個由類的實現者控制的子集。用戶只能用 const_cast 來獲得對類型接口的完全訪問。此外, volatile 向 const 一樣會從類傳遞到它的成員。

一般說來,volatile用在如下的幾個地方:
中斷服務程序中修改的供其它程序檢測的變量需要加volatile;
多任務環境下各任務間共享的標誌應該加volatile;
存儲器映射的硬件寄存器通常也要加volatile說明,因爲每次對它的讀寫都可能由不同意義。
參考:
http://www.cnblogs.com/Chase/archive/2010/07/05/1771700.html
http://blog.csdn.net/wwang196988/article/details/6623387

上行轉換 下行轉換
上行轉換(up-casting)
上行轉換的“上”表示沿繼承鏈向上走(向父類的方向走)。
下行轉換(down-casting)
下”表示沿着繼承鏈向下走(向子類的方向走)。
上行轉換一般是安全的,下行轉換很可能是不安全的。
針對類指針的問題,C++特別設計了更加細緻的轉換方法:
static_cast、dynamic_cast、reinterpret_cast和const_cast

static_cast(靜態類型轉換)
用法:static_cast <typename> (expression)
說明:該運算符把expression轉換爲typename類型,但沒有運行時類型檢查來確保轉換的安全性。
用途:
a) 用於類層次結構中基類和派生類之間指針或者引用的轉換。up-casting (把派生類的指針或引用轉換成基類的指針或者引用表示)是
安全的;down-casting(把基類指針或引用轉換成子類的指針或者引用)是不安全的。
b) 用於基本數據類型之間的轉換,如把int轉換成char,這種轉換的安全性也要由開發人員來保證。
c) 可以把空指針轉換成目標類型的空指針(null pointer)。
d) 把任何類型的表達式轉換成void類型。
注意: static_cast不能轉換掉expression的const、volitale或者__unaligned屬性。

但是static_cast 相對來說已經安全很多了


#include <iostream>
using namespace std;

class CDummy {
    float i,j;
};

class CAddition {
    int x,y;
  public:
    CAddition (int a, int b) { x=a; y=b; }
    int result() { return x+y;}
};

int main () {
  int a = 1;
  double b = static_cast<double> (a); //ok
  CDummy d;
  CAddition * padd;
  padd = (CAddition *) (&d);//ok,雖然是不安全的下行轉換,但是編譯器並沒有報錯
  //padd = static_cast< CAddition * > (&d);  error, 報錯
  //Untitled1.cpp|22|error: invalid static_cast from type     //'CDummy*' to type 'CAddition*'|

  cout << padd->result();
  return 0;
}

dynamic_cast (expression) 動態轉換
參考:
http://www.cnblogs.com/findumars/archive/2012/04/08/2437901.html
http://www.cplusplus.com/doc/tutorial/typecasting/
http://msdn.microsoft.com/en-us/library/cby9kycs
用法:dynamic_cast (expression)
具有類型檢查的功能,比static_cast更安全。檢測在運行時進行。如果被轉換的指針不是一個被請求的有效完整的對象指針,返回值爲NULL。
說明:該運算符把expression轉換成typeid類型的對象。typeid必須是類的指針、類的引用或者void*。如果typeid是類的指針類型,
那麼expression也必須是指針,如果typeid是一個引用,那麼expression也必須是一個引用。一般情況下,dynamic_cast用
於具有多態性的類(即有虛函數的類)的類型轉換。
dynamic_cast依賴於RTTI信息,在轉換時,dynamic_cast會檢查轉換的source對象是否真的可以轉換成target類型,
這種檢查不是語法上的,而是真實情況的檢查。先看RTTI相關部分,通常,許多編譯器都是通過vtable找到對象的RTTI信息 的,這也就意味着,如果基類沒有虛方法,也就無法判斷一個基類指針變量所指對象的真實類型,這時候,dynamic_cast只能
用來做安全的轉換,例如從派生類指針轉換成基類指針。而這種轉換其實並不需要dynamic_cast參與。也就是說,dynamic_cast 是根據RTTI記載的信息來判斷類型轉換是否合法的。
注意:dynamic_cast不能轉換掉expression的const、volitale或者__unaligned屬性。

#include <iostream>
using namespace std;
class CBase { };
class CDerived: public CBase { };

int main()
{
CBase b; CBase* pb;
CDerived d; CDerived* pd;

pb = dynamic_cast<CBase*>(&d);     // ok: derived-to-base
pd = dynamic_cast<CDerived*>(&b);  // wrong: base-to-derived
}

但是改成這樣

class CBase {virtual void dummy() {}  };

OK的,但是當我們輸出pb,pd的時候問題來了:
0x28fef0
0
pd是0,也就是NULL
這正是dynamic_cast提升安全性的功能,dynamic_cast可以識別出不安全的下行轉換,但並不拋出異常,而是將轉換的結果設置成null(空指針)。

下面我們來看一個很神奇的事情

#include <iostream>
#include <exception>
using namespace std;

class CBase { virtual void dummy() {} };
class CDerived: public CBase { int a; };

int main () {
  try {
    CBase * pba = new CDerived;
    CBase * pbb = new CBase;
    CDerived * pd;

    pd = dynamic_cast<CDerived*>(pba);
    if (pd==0) cout << "Null pointer on first type-cast" << endl;

    pd = dynamic_cast<CDerived*>(pbb);
    if (pd==0) cout << "Null pointer on second type-cast" << endl;

  } catch (exception& e) {cout << "Exception: " << e.what();}
  return 0;
}

輸出結果是:Null pointer on second type-cast

兩個dynamic_cast都是下行轉換,第一個轉換是安全的,因爲指向對象的本質是子類,轉換的結果使子類指針指向子類,天經地義;第二個轉換是不安全的,因爲指向對象的本質是父類,“指鹿爲馬”或指向不存在的空間很可能發生!
最後補充一個特殊情況,當待轉換指針是void*或者轉換目標指針是void*時,dynamic_cast認爲空指針的轉換安全的,但這裏類A和類B必須是多態的,包含虛函數,若不是,則會編譯報錯。

reinterpret_cast (expression) 重解釋轉換
說明:轉換一個指針爲其他類型的指針,也允許將一個指針轉換爲整數類型,反之亦然。這個操作符能夠在非相關的類型之間進行
轉換。操作結果只是簡單的從一個指針到別的指針的值的二進制拷貝,在類型之間指向的內容不做任何類型的檢查和轉換。這
是一個強制轉換。使用時有很大的風險,慎用之。
注意:reinterpret _cast不能轉換掉expression的const、volitale或者__unaligned屬性。
這個轉換是最“不安全”的,兩個沒有任何關係的類指針之間轉換都可以用這個轉換實現,

const_cast (expression) 常量向非常量轉換
說明:這個類型操縱傳遞對象的const屬性,或者是設置或者是移除。如:

Class C{…}

           const C* a = new C;

           C* b = const_cast<C*>(a);

如果將上面的const_cast轉換成其他任何其他的轉換,編譯都不能通過,出錯的信心大致如下:
“…cannot convert from ‘const class C ’ to ‘class C ‘”。

發佈了448 篇原創文章 · 獲贊 3 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章