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 ‘”。