Note:以下結論不適用於類的成員函數指標,關於類的成員函數指標會單獨討論。
一、任何類型的指標變數均可直接賦值給const void *
任何類型的非const指標變數均可直接賦值給void *
const指標變數不可直接賦值給void *,除非通過強制類型轉換
class A{};typedef int (*pFun)(string); //函數指標int *pInt;const int *pInt_c;char *pChar;const char *pChar_c;double *pDouble;const double *pDouble_c;A *pA; //自訂類型指標const A *pA_c;pFun pf;//函數指標void* pVoid;const void* pVoid_c;// 1.任何類型的指標變數均可直接賦值給const void *pVoid_c = pInt; //okpVoid_c = pInt_c; //okpVoid_c = pChar; //okpVoid_c = pChar_c; //okpVoid_c = pDouble; //okpVoid_c = pDouble_c; //okpVoid_c = pA; //okpVoid_c = pA_c; //okpVoid_c = pf; //ok// 2.任何類型的非const指標變數均可直接賦值給void *pVoid = pInt; //okpVoid = pChar; //okpVoid = pDouble; //okpVoid = pA; //okpVoid = pf; //ok// 3.const指標變數不可直接賦值給void *,除非通過強制類型轉換pVoid = pInt_c; //error: cannot convert from 'const int *' to 'void *'pVoid = pChar_c; //error: cannot convert from 'const char *' to 'void *'pVoid = pDouble_c; //error: cannot convert from 'const double *' to 'void *'pVoid = pA_c; //error: cannot convert from 'const A *' to 'void *'pVoid = (void*)pInt_c; //okpVoid = (void*)pChar_c; //okpVoid = (void*)pDouble_c; //okpVoid = (void*)pA_c; //ok
二、任意類型指標變數之間均可以強制類型轉換,包括const與非const指標變數之間的強制類型轉換。
pInt = (int*)pDouble; //okpInt = (int*)pf; //okpInt = (int*)pInt_c; //ok:由const指標變數轉非const指標變數pInt = (int*)pA_c; //ok:由const指標變數轉非const指標變數pA = (A*)pA_c; //ok:由const指標變數轉非const指標變數pA = (A*)pDouble; //okpA = (A*)pf; //ok pf = (pFun)pDouble; //okpf = (pFun)pA; //ok
三、有繼承關係的自訂類型之間:子類型指標變數可直接賦值給父類型指標變數
父類型指標變數不可直接賦值給子類型指標變數,除非通過強制類型轉換
class A{};class B : public A // B繼承自A{};class C{};A* pA;B* pB;C* pC;pA = pB; //ok: 子類型指標變數可直接賦值給父類型指標變數pB = pA; //error: 父類型指標變數不可直接賦值給子類型指標變數,除非強制類型轉換 //以下適用規則二:pA = (A*)pC;//okpB = (B*)pA;//okpB = (B*)pC;//okpC = (C*)pA;//okpC = (C*)pB;//ok
補充:
1、對於類的成員函數指標,以上原則不適用。
class A{};typedef void (A::*AFunPointer)(void);typedef void (*FunPtr)(void);void * pVoid;int * pInt;FunPtr fp;AFunPointer afp;pVoid = afp; //error: cannot convert from 'AFunPointer' to 'void *'pInt = (int*)afp; //error: 'type cast' : cannot convert from 'AFunPointer' to 'int *'fp = (FunPtr)afp; //error: 'type cast' : cannot convert from 'AFunPointer' to 'FunPtr'afp = (AFunPointer)pInt; //error: 'type cast' : cannot convert from 'int *' to 'AFunPointer'afp = (AFunPointer)pVoid; //error: 'type cast' : cannot convert from 'void *' to 'AFunPointer'afp = (AFunPointer)fp; //error: 'type cast' : cannot convert from 'FunPtr' to 'AFunPointer'
我們可以這樣理解:類的成員函數指標被限定在具體的某個類的範圍中了,他不能和域外的指標之間轉換。
2、除去類的成員函數指標,雖然任意類型指標變數之間均可以強制類型轉換,也即可以將const指標強轉為非const指標。
但是應注意:如果將const指標強轉為非const指標而用於原本const的對象,則產生未定義行為(C++語言未對此種情況進行規定)。如:
const int a = 50; // 定義const變數及常量const int* p = &a; // const指標變數p指向const變數aint* q = (int*)p; // const指標強轉為非const指標,則非const指標變數q指向const變數a*q = 56; // 行為未定義,以下輸出為VS2008下的輸出結果cout << a << endl; //輸出: 50cout << *p << endl; //輸出: 56,很顯然,p已經不指向a了cout << *q << endl; //輸出: 56,很顯然,q已經不指向a了
3、關於一般函數指標的強制轉換,以下當然也是OK的。
class A;typedef void (*pFun1)(int, int);typedef int (*pFun2)(A*, double);pFun1 pf1;pFun2 pf2;pf2 = (pFun2)pf1; // OK