您的位置:首页 > 编程语言 > C语言/C++

常量指针、指针常量、C++类型转换

2015-09-10 22:05 465 查看
一、const应用

1.const关键字,他后面内容的不可修改,一般来说,其修饰的变量不可再进行赋值操作;

2.常量指针

int a = 3;

int b = 4;

const int* pt = &a;

a = 5;

*pt的值为5,pt只是一个指针,所以他指向的是a的内容,const限制的是*pt,所以,只是不能通过*pt修改其指向的内存内容.

3.指针常量:int* const a = pt;由于不可再进行赋值操作,所以指针常量在声明时必须赋值;

相关文章:

一、常指针与指针常量的区别?

1 常量指针!如 int b, c; int * const a = &b;

表示a是一个常量指针它指向变量b的内存。但是 因为是常量指针所以不能再用a指向其他变量,如 a = &c; 错误!可以修改指向内存的值,如:*a = 20; BTW 常量指针声明的时候必须向我那样赋初值。

2 指向常量的指针!如 int b, c; int const *a; a = &b; a = &c;

都可以,唯独它指向的内存不能被修改。如:*a=20;这是违法的!错误!

这就是主 要区别!

BTW 还有一个记住他们不同形式的技巧!看const关键字,他后面的不可修改,如int * const a = &b; 后面是a,则说明a不能修改!

int const * a = &b;后面是*a则说明*a不可被修改!


在 好多书上或MSDN是经常用 const int a=5;

int b=6;

const int *p=&b;

其实 const int* 和int const* 一样,就是常指针 也就是它所指向的数据(在这是int)是常量,它自己的数据类型是const int*

还有const int *p=&b;是可以的 虽然b不是常量。

但是 const int a=6;

int *p=&a;

会报错,因为它消除了a的const属性


**********************************************

******* 我们可以总结一下********

1. 对于常量(符号常量)和常指针、常引用常对象声明都是一样的

定义格式: const 数据类型 常量名=常量值;

或 数据类型 const 常量名=常量值;


例如:const int a=7; 或 int const a=7;(符号常量)

int b=5;

const int *p=&b; 或 int const *p=&b;(常指针)

const int &m=b;(常引用)

const Point pt; 或 Point const pt; //常对象不能更新

常指针和常引用在功能上有所限制,就是不能通过他们更改其指向的变量的数据(值)

2. 指针常量

定义格式: 数据类型 *const 指针常量=常量值;

如char ch,*const pch=&ch;(我是一步完成的,你也可以分开)

也就是说这个指针本身是个常量,不可改变,即它所指向的地址是固定的。但,ch是可以 改变的。

二、c++中有常指针和指针常量的概念,c中有吗?

char *p="abc"

"abc"叫字符字面常 量,指针是可以变的,但是指针指向的这段字符串不可修改

char a[]="def"

这个a是数组,a本身不可变,但a的内 容"def"可以变

const char *p

p指向的字符串是常量,不可变;但p指针本身可以变化,也就是说可以指向另外一个 地址

char* const p

p是指针常量,只能指向最初的那个地址,需要在定义时赋值,因为一旦定义,指针p就不能改变;但 p指向的内容是可以变化的。


二、类型转换

reinterpret_cast,const_cast,static_cast,dynamic_cast 总结

#include

int main(void)

{

//reinterpret_cast

//将一个类型指针转换为另一个类型指针,这种在转换不修改指针变量值 数据存放格式

//只需在编译时重新解释指针的类型,他可以将指针转化为一个整型数但不能用于非指针的转换


double d=9.3;

double* pd = &d;

int* pi = reinterpret_cast (pd);

class A{};

class B{};

A* pa = new A;

B* pb=reinterpret_cast(pa); //将pa 转为B

long j=reinterpret_cast (pa);//指针转换为整数

// int i=9;

// double x=reinterpret_cast(i); //reinterpret_cast不能用于非指针的转换


//const_cast

该运算符用来修改类型的const或 volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。

一、常量指针被转化成非常量指针,并且仍然指向原来 的对象;

二、常量引用被转换成非常量引用,并且仍然指向原来 的对象;

三、常量对象被转换成非常量对象。

//1. 用于去除指针变量的常属性,将它转换为一个对应指针类型的普通变量,

//2.反过来也可以将一个非常量指针转换为一个常量指针变量

//3. 他无法将一个非指针的常量转换为普通变量

//example: const i=10;

// int j=const_cast(i); //无法转换


const int ppp=998;

const int* pca=&ppp;

int* p=const_cast(pca);//将它转换为一个对应指针类型的普通变量,去除了const;

const A* paa=new A;

A * ppppa=const_cast (paa);//它转换为一个对应指针类型的普通变量,去除了const;

int * pii=0;//反过来也可以将一个非常量指针转换为一个常量指针变量

const int* piiic=const_cast(pii);

//////////////////////////////////////////////////////////////////////////////////

//static_cast

//用于转换基本类型和具有 继承关系的类新之间转换

//static_cast不太用于指针类型的之间的转换,他的效率没有reinterpret_cast的效率高


int in=99;

double dn=static_cast (in);// 用于转换基本类型和具有继承关系的类新之间转换

class Base{};

class derv:public Base{};

derv dd;

Base bbbb=static_cast(dd);// 具有继承关系的类新之间转换

//static_cast 不太用于指针类型的之间的转换,他的效率没有reinterpret_cast的效率高

Base *pb1=new Base;

derv *pder=static_cast(pb1);//基类转继承类

derv* pder1=new derv;

Base* pbase1=static_cast(pder1);// 继承类指针转父类指针

//////////////////////////////////////////////////////////////////////////

//dynamic_cast

//1.只能在继承类对象的指 针之间或引用之间进行类型转换

//2.这种转换并非在编译时,而是在运行时,动态的

//3.没有继承关系,但被转换的类具有虚函数对象的 指针进行转换


derv* dp=new derv;

Base* bv=dynamic_cast(dp);//继承类对象的指针之间进行类型转换

derv dpp;//继承类对象引用之间进行类型转换

Base &b=dynamic_cast(dpp);

class AA{virtual fun(){}

virtual ~AA(){}};

class BB{};

//没有继承关系,但被转换的类具有虚函数对象的指针进行转换,编译可通过

AA* pAA=new AA;

BB* pBB=dynamic_cast(pAA);

//没有继承关系,被转换的类也没有有虚函数对象的指针进行转换,编译不能通过

BB* pBBB=new BB;

AA* pAAA=dynamic_cast(pBBB);

return 1;

}





//总结:

//reinterpret_cast 将一个类型指针转换为另一个类型指针

//const_cast 用于去除指针变量的常属性,将它转换为一个对应指针类型的普通变量,反过来也可以将一个非常量指针转换为一个常量指针变量

//static_cast 用于转换基本类型和具有继承关系的类新之间转换,不太用于指针类型的之间的转换

//dynamic_cast 只能在继承类对象的指针之间或引用之间进行类型转换

//以上只有dynamic_cast这种转换并非在编译时,而是在运行时,动态的。其它均在 编译时


——————————————————————————————————————

标准C++的类型转换符:static_cast、dynamic_cast、 reinterpret_cast、和const_cast。

static_cast

用法:static_cast < type-id > ( exdivssion )

该运算符把exdivssion转换为type-id类型,但没有运行时类型检查来保证转换的安全性。它主要有 如下几种用法:

①用于类层次结构中基类和子类之间指针或引用的转换。

  进行上行转换(把子类的指针或引用转换成基类表示)是安全的;

   进行下行转换(把基类指针或引用转换成子类表示)时,由于没有动态类型检查,所以是不安全的。

②用于基本数据类型之间的转换,如把int转换成 char,把int转换成enum。这种转换的安全性也要开发人员来保证。

③把空指针转换成目标类型的空指针。

④把任何类型的表达式转换 成void类型。

注意:static_cast不能转换掉exdivssion的const、volitale、或者 __unaligned属性。

dynamic_cast

用法:dynamic_cast < type-id > ( exdivssion )

该运算符把exdivssion转换成type-id类型的对象。Type-id必须是 类的指针、类的引用或者void *;

如果type-id是类指针类型,那么exdivssion也必须是一个指针,如果type-id是一个引 用,那么exdivssion也必须是一个引用。

dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。

在 类层次间进行上行转换时,

dynamic_cast和static_cast的效果是一样的;

在进行下行转换 时,dynamic_cast具有类型检查的功能,比static_cast更安全。

class B{

public:

int m_iNum;

virtual void foo();

};

class D:public B{

public:

char *m_szName[100];

};

void func(B *pb){

D *pd1 = static_cast(pb);

D *pd2 = dynamic_cast((pb);

}

在上面的代码段中,如果pb指向一个D类型的对象,pd1和pd2是一样的,并且对这两个指针执行D 类型的任何操作都是安全的;

但是,如果pb指向的是一个B类型的对象,那么pd1将是一个指向该对象的指针,对它进行D类型的操作将是不安全的 (如访问m_szName),

而pd2将是一个空指针。

另外要注意:B要有虚函数,否则会编译出错;static_cast则没有这个限制。

这是由 于运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表(

关于虚函数表的概念,详细可见)中,只有定义了虚函数的类才有虚函数表,

没 有定义虚函数的类是没有虚函数表的。


另外,dynamic_cast还支持交叉转换(cross cast)。如下代码所示。

class A{

public:

int m_iNum;

virtual void f(){}

};

class B:public A{

};

class D:public A{

};

void foo(){

B *pb = new B;

pb->m_iNum = 100;

D *pd1 = static_cast((pb); //compile error

D *pd2 = dynamic_cast((pb); //pd2 is NULL

delete pb;

}

在函数foo中,使用static_cast进行转换是不被允许的,

将在编译时出错;而使用 dynamic_cast的转换则是允许的,结果是空指针。

reinterpret_cast

用法:reinterpret_cast< type-id >(exdivssion)

type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。

它可以把一个 指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,

在把该整数转换成原类型的指针,还可以得到原先的指针值)。

该运算符的用法比较多。

const_cast

用法:const_cast< type-id > (exdivssion)

该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和exdivssion的类型是一样的。

常量指针被转化成非常量指针,并且仍然指向原来的对象;

常量引用被转换成非常量引 用,并且仍然指向原来的对象;常量对象被转换成非常量对象。


Voiatile和const类试。举如下一例:

class B{

public:

int m_iNum;

}

void foo(){

const B b1;

b1.m_iNum = 100; //comile error

B b2 = const_cast((b1);

b2. m_iNum = 200; //fine

}

上 面的代码编译时会报错,因为b1是一个常量对象,不能对它进行改变;

使用const_cast把它转换成一个常量对象,就可以对它的数据成员任意 改变。注意:b1和b2是两个不同的对象。


转自:http://blog.chinaunix.net/uid-22889411-id-59671.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: