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 
//
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

C++指针之间的赋值与转换规则总结的更多相关文章

  1. C++:基类与派生类对象之间的赋值兼容关系

    4.5 基类与派生类对象之间的赋值兼容关系 在一定条件下,不同类型的数据之间可以进行类型转换,例如可以将整型数据赋给双精度型变量. 在赋值之前,先把整型数据转换为双精度型数据,然后再把它双精度型变量. ...

  2. C语言_指针变量的赋值与运算,很详细

    指针变量的赋值 指针变量同普通变量一样,使用之前不仅要定义说明, 而且必须赋予具体的值.未经赋值的指针变量不能使用, 否则将造成系统混乱,甚至死机.指针变量的赋值只能赋予地址, 决不能赋予任何其它数据 ...

  3. JS面向对象(2) -- this的使用,对象之间的赋值,for...in语句,delete使用,成员方法,json对象的使用,prototype的使用,原型继承与原型链

    相关链接: JS面向对象(1) -- 简介,入门,系统常用类,自定义类,constructor,typeof,instanceof,对象在内存中的表现形式 JS面向对象(2) -- this的使用,对 ...

  4. 使用 Attribute +反射 来对两个类之间动态赋值

    看同事使用的 一个ORM 框架 中 有这样一个功能  通过特性(附加属性)的功能来 实现的两个类对象之间动态赋值的 功能 觉得这个功能不错,但是同事使用的 ORM 并不是我使用的  Dapper  所 ...

  5. [C]关于函数指针参数的赋值

    问题 在有一次尝试用stat()函数获取文件属性的时候,发现如果直接声明一个指针,然后把这个指针作为参数传给函数,会导致函数执行失败,原代码: #include <sys/stat.h> ...

  6. C++ 指针悬挂和赋值操作符的重载,拷贝构造函数实现

    指针悬挂: 问题:使用new申请的内存内存空间无法访问,也无法释放. 原因:直接对指向new申请的存储空间的指针变量进行赋值修改 后果:失去了原来的地址,原来的空间无法访问也无法释放,造成内存泄漏 还 ...

  7. [错误记录_C] 还未给指针变量正确赋值的情况下,就使用它的值

    错误的代码: 错误的结果:  错误原因分析: 在使用(1) 将pB,pC的值赋给pA的lchild和rchild时: 还未给指针变量pB和pC赋值,现在pB和pC中存的是个垃圾值 Note: (2)- ...

  8. c语言中通过指针将数值赋值到制定内存地址

    1.一种直观的方法 假设现在需要往内存0x12ff7c地址上存入一个整型数0x100.我们怎么才能做到呢? 我们知道可以通过一个指针向其指向的内存地址写入数据,那么这里的内存地址0x12ff7c其本质 ...

  9. [转载]delete指针之后应该赋值NULL

    首先,C++标准规定:delete空指针是合法的,没有副作用.但是,delete p后,只是释放了指针指向的内存空间.p并不会自动被置为NULL,而且指针还在,同时还指向了之前的地址. 问题来了,对一 ...

随机推荐

  1. C#之Clone

    因为类的实例是引用类型,要想用原有的类中的实例的数据的话,既要想创建原对象的一个副本的话,只能用clone方法. Clone方法分为深clone和浅clone 在C#中提供了浅clone的方法,即为M ...

  2. js 浮点数计算Bug

    之前在写项目时候,直接对带小数点的数据进行运算,发现所得到的值并不是自己想要的. 经过一系列学习后,发现在JavaScript中,浮点数运算都是先转换成二进制,在转成二进制的时候有出现无限循环小数,故 ...

  3. IE浏览器在线更新GitHub客户端

    在IE中输入网址:http://github-windows.s3.amazonaws.com/GitHub.application

  4. 快速配置$XX_TOP方法

    查找配置文件名 执行:env | grep CONTEXT 得到: CONTEXT_FILE=/dev01/oracle/UAT/inst/apps/UAT_ksebsdt/appl/admin/UA ...

  5. [RDLC]心得整理(一)

    2014年在做项目的时候, 过用过RDLC, 之后便在没有使用过了. 最近又有项目使用rdlc, 感觉有些陌生,然后重新阅读了以前的笔记,想做一下整理. 常见问题: 1. 为什么rdlc报表出来的pd ...

  6. So you want to write a desktop app in Python

    So you want to write a desktop app in Python Thomas Kluyver 2014-06-16 23:55 51 Comments Source This ...

  7. PHP:substr和mb_substr的区别

    substr和mb_substr函数都是获取字符串中的某个部分 那么,它们的区别在哪儿呢? 区别: substr :全部是英语.数字就正常:但有一些的字元是占用多个位元的,substr()就得不到你预 ...

  8. 【BZOJ5212】[ZJOI2018] 历史(LCT大黑题)

    点此看题面 大致题意: 给定一棵树每个节点\(Access\)的次数,求最大虚实链切换次数,带修改. 什么是\(Access\)? 推荐你先去学一学\(LCT\)吧. 初始化(不带修改的做法) 首先考 ...

  9. 引用类型(二):Array类型

    一.js中的数组与其它语言中的数组的区别1.ECMAScript数组的每一项可以保存任何类型的数据2.ECMAScript数组的大小是可以动态调整的 二.创建数组的基本方式1.使用Array构造函数 ...

  10. 20145238-荆玉茗 《Java程序设计》第4周学习总结

    20145238 <Java程序设计>第4周学习总结 教材学习内容总结第六章 继承与多态 6.1.1 ·继承基本上就是避免多个类间重复定义共同行为. 在游戏中会有很多程序代码重复的片段,这 ...