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; //ok pVoid_c = pInt_c; //ok pVoid_c = pChar; //ok pVoid_c = pChar_c; //ok pVoid_c = pDouble; //ok pVoid_c = pDouble_c; //ok pVoid_c = pA; //ok pVoid_c = pA_c; //ok pVoid_c = pf; //ok // 2.任何類型的非const指針變量均可直接賦值給void * pVoid = pInt; //ok pVoid = pChar; //ok pVoid = pDouble; //ok pVoid = pA; //ok pVoid = 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; //ok pVoid = (void*)pChar_c; //ok pVoid = (void*)pDouble_c; //ok pVoid = (void*)pA_c; //ok
二、任意類型指針變量之間均可以強制類型轉換,包括const與非const指針變量之間的強制類型轉換。
pInt = (int*)pDouble; //ok pInt = (int*)pf; //ok pInt = (int*)pInt_c; //ok:由const指針變量轉非const指針變量 pInt = (int*)pA_c; //ok:由const指針變量轉非const指針變量 pA = (A*)pA_c; //ok:由const指針變量轉非const指針變量 pA = (A*)pDouble; //ok pA = (A*)pf; //ok pf = (pFun)pDouble; //ok pf = (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; //ok pB = (B*)pA; //ok pB = (B*)pC; //ok pC = (C*)pA; //ok pC = (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變量a int* q = (int*)p; // const指針強轉為非const指針,則非const指針變量q指向const變量a *q = 56; // 行為未定義,以下輸出為VS2008下的輸出結果 cout << a << endl; //輸出: 50 cout << *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