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. Flask文件目录----- auth/blog 文件

    import functools from flask import (Blueprint, flash, g, redirect, render_template, url_for, request ...

  2. (C# 基础) 静态字段,静态类,静态方法。

    静态字段被类的所有实例所共享,即此类的所有实例都访问同一内存地址. 所以该内存位置的值变更的话,这种变更对所有的实例都可见. class MyClass { ; ; public void SetVa ...

  3. ndk制作so库,ndk-build不是内部或外部命令。。。的错误

    想了想大概就需要下面这几步: 1.下载ndk 2.配置ndk的环境变量 3.在android studio添加一些ndk的配置 4.编写c文件 5.生成so库 6.调用so库 上面提到的大部分问题你都 ...

  4. 《ArcGIS Runtime SDK for Android开发笔记》——(1)、Android Studio下载与安装

    1.前言 Android Studio 是一个Android开发环境,基于IntelliJ IDEA. 类似 Eclipse ADT,Android Studio 提供了集成的 Android 开发工 ...

  5. xcode import pod 文件不提示

    在使用第三方类库时,使用cocoaPods是非常方便的,具体使用方法可以参考:CocoaPods安装和使用教程 的安装使用方法.今天讨论的问题是,我在使用的时候遇到了一些问题:用cocoaPod si ...

  6. Zamplus 晶赞天机

    类型: 定制服务 软件包: car/vehicle integrated industry solution collateral tourism 联系服务商 产品详情 解决方案 概要 DMP:通常称 ...

  7. IDEA 打包jar

    1.ctrl+shift+alt+s 弹出项目设置窗口,点击Artifacts页签,点+号,选择jar Empty.修改jar name,将右侧需要打包进去的资源拖到左侧,记住Output direc ...

  8. php中增删改查以及返回结果(一)

    虽然毕业后找的第一份正式的工作并不那么令人满意,但是在度过最初的迷茫期后,自己还是决定成为一个程序猿. 最近也是利用上班偶尔闲下来的时间,开始看书,撸代码,写一些小程序. 这两个礼拜主要的写的都是有关 ...

  9. 中兴ZXR10 GER4核心路由器配置案例

    Connecting to 192.168.100.2:23...Connection established.To escape to local shell, press 'Ctrl+Alt+]' ...

  10. 用户表单事件(focus事件)

    以前做用户系统的时候经常用到表单验证,正则表达式事件来处理和绑定事件和进行事件,这里说的其实只是一小部分,也不是很值得写,但是今天遇到了还是写一下,毕竟基础还是蛮重要的,就算懂的童鞋,巩固一下也是好的 ...