C++指针之间的赋值与转换规则总结
Note:以下结论不适用于类的成员函数指针,关于类的成员函数指针会单独讨论。
一、任何类型的指针变量均可直接赋值给const void *
任何类型的非const指针变量均可直接赋值给void *
const指针变量不可直接赋值给void *,除非通过强制类型转换
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
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指针变量之间的强制类型转换。
|
1
2
3
4
5
6
7
8
9
|
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
|
三、有继承关系的自定义类型之间:子类型指针变量可直接赋值给父类型指针变量
父类型指针变量不可直接赋值给子类型指针变量,除非通过强制类型转换
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
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、对于类的成员函数指针,以上原则不适用。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
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++语言未对此种情况进行规定)。如:
|
1
2
3
4
5
6
7
|
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
Note:以下结论不适用于类的成员函数指针,关于类的成员函数指针会单独讨论。
一、任何类型的指针变量均可直接赋值给const void *
任何类型的非const指针变量均可直接赋值给void *
const指针变量不可直接赋值给void *,除非通过强制类型转换
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
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指针变量之间的强制类型转换。
|
1
2
3
4
5
6
7
8
9
|
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
|
三、有继承关系的自定义类型之间:子类型指针变量可直接赋值给父类型指针变量
父类型指针变量不可直接赋值给子类型指针变量,除非通过强制类型转换
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
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、对于类的成员函数指针,以上原则不适用。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
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++语言未对此种情况进行规定)。如:
|
1
2
3
4
5
6
7
|
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