常量指针,指针常量,C++类型转换[转]
一、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中有吗?
"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<iostream.h>
int main(void)
{
//reinterpret_cast
//将一个类型指针转换为另一个类型指针,这种在转换不修改指针变量值
数据存放格式
//只需在编译时重新解释指针的类型,他可以将指针转化为一个整型数但不能用于非指针的转换
double
d=9.3;
double* pd = &d;
int* pi = reinterpret_cast<int *>
(pd);
class A{};
class B{};
A* pa = new A;
B*
pb=reinterpret_cast<B*>(pa); //将pa 转为B
long
j=reinterpret_cast<long> (pa);//指针转换为整数
// int i=9;
// double
x=reinterpret_cast<double>(i); //reinterpret_cast不能用于非指针的转换
//const_cast
该运算符用来修改类型的const或 volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。
一、常量指针被转化成非常量指针,并且仍然指向原来 的对象;
二、常量引用被转换成非常量引用,并且仍然指向原来 的对象;
三、常量对象被转换成非常量对象。
//1.
用于去除指针变量的常属性,将它转换为一个对应指针类型的普通变量,
//2.反过来也可以将一个非常量指针转换为一个常量指针变量
//3.
他无法将一个非指针的常量转换为普通变量
//example: const
i=10;
// int
j=const_cast<int>(i); //无法转换
const int
ppp=998;
const int*
pca=&ppp;
int*
p=const_cast<int*>(pca);//将它转换为一个对应指针类型的普通变量,去除了const;
const A* paa=new A;
A *
ppppa=const_cast<A*> (paa);//它转换为一个对应指针类型的普通变量,去除了const;
int *
pii=0;//反过来也可以将一个非常量指针转换为一个常量指针变量
const int* piiic=const_cast<const int
*>(pii);
//////////////////////////////////////////////////////////////////////////////////
//static_cast
//用于转换基本类型和具有
继承关系的类新之间转换
//static_cast不太用于指针类型的之间的转换,他的效率没有reinterpret_cast的效率高
int in=99;
double
dn=static_cast<double> (in);//
用于转换基本类型和具有继承关系的类新之间转换
class Base{};
class derv:public
Base{};
derv dd;
Base bbbb=static_cast<Base>(dd);//
具有继承关系的类新之间转换
//static_cast
不太用于指针类型的之间的转换,他的效率没有reinterpret_cast的效率高
Base *pb1=new
Base;
derv
*pder=static_cast<derv*>(pb1);//基类转继承类
derv* pder1=new
derv;
Base* pbase1=static_cast<Base*>(pder1);//
继承类指针转父类指针
//////////////////////////////////////////////////////////////////////////
//dynamic_cast
//1.只能在继承类对象的指
针之间或引用之间进行类型转换
//2.这种转换并非在编译时,而是在运行时,动态的
//3.没有继承关系,但被转换的类具有虚函数对象的
指针进行转换
derv* dp=new derv;
Base* bv=dynamic_cast<Base
*>(dp);//继承类对象的指针之间进行类型转换
derv
dpp;//继承类对象引用之间进行类型转换
Base
&b=dynamic_cast<Base&>(dpp);
class AA{virtual fun(){}
virtual
~AA(){}};
class BB{};
//没有继承关系,但被转换的类具有虚函数对象的指针进行转换,编译可通过
AA*
pAA=new AA;
BB* pBB=dynamic_cast<BB *>(pAA);
//没有继承关系,被转换的类也没有有虚函数对象的指针进行转换,编译不能通过
BB*
pBBB=new BB;
AA* pAAA=dynamic_cast<AA*>(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<D *>(pb);
D *pd2 = dynamic_cast<D
*>((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<D *>((pb);
//compile error
D *pd2 = dynamic_cast<D *>((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<B>((b1);
b2. m_iNum = 200;
//fine
}
上
面的代码编译时会报错,因为b1是一个常量对象,不能对它进行改变;
使用const_cast把它转换成一个常量对象,就可以对它的数据成员任意
改变。注意:b1和b2是两个不同的对象。