C++指針之間的賦值與轉換規則總結


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM