static_const 和const_cast

关于强制类型转换的问题,很多书都讨论过,写的最详细的是C++ 之父的《C++的设计和演化》。最好的解决方法就是不要使用C风格的强制类型转换,而是使用标准C++的类型转换符static_cast, dynamic_cast。标准C++中有四个类型转换符:static_castdynamic_castreinterpret_cast、和 const_cast。下面对它们一一进行介绍。

 

I. static_cast

例如,假设你想把一个int转换成double,以便让包含int类型变量的表达式产生出浮点数值的结果。如果用C风格的类型转换,你能这样写: 
int firstNumber, secondNumber; 
  ... 
  double result = ((double)firstNumber)/secondNumber

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

double result = static_cast <double> (firstNumber)/secondNumber;

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

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

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

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

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

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

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

它也有功能上限制。例如,你不能用static_cast象用C风格的类型转换一样把struct转换成int类型或者把double类型转换成指针类型,另外,static_cast不能从表达式中去除const属性,因为另一个新的类型转换操作符const_cast有这样的功能。

注意:static_cast不能转换掉expressionconstvolitale、或者__unaligned属性。

IV. const_cast

用法:const_cast<type_id> (expression)

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

 

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

 

Voiatileconst类试。举如下一例:

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把它转换成一个常量对象,就可以对它的数据成员任意改变。注意:b1b2是两个不同的对象。

class Widget { ... }; 
  class SpecialWidget: public Widget { ... }; 
  void update(SpecialWidget *psw); 
  SpecialWidget sw; // sw 是一个非const 对象 
  const SpecialWidget& csw = sw; // csw sw的一个引用 
   // 它是一个const 对象 

  update(&csw); // 错误!不能传递一个const SpecialWidget* 变量 
  // 给一个处理SpecialWidget*类型变量的函数 

  update(const_cast <SpecialWidget*> (&csw)); 
     // 正确,cswconst被显示地转换掉( 
     // cswsw两个变量值在update 
    // 函数中能被更新) 

  update((SpecialWidget*)&csw); 
  // 同上,但用了一个更难识别 
  // C风格的类型转换 

  Widget *pw = new SpecialWidget; 

  update(pw); // 错误!pw的类型是Widget*,但是 
  // update函数处理的是SpecialWidget*类型 

  update(const_cast <SpecialWidget*> (pw)); 
   // 错误!const_cast仅能被用在影响 
  // constness or volatileness的地方上。 
  // 不能用在向继承子类进行类型转换。 

  到目前为止,const_cast最普通的用途就是转换掉对象的const属性.

class widget{};

class subwidget:public widget{};

void update(subwidget *w)

{}

void update1(widget *w)

{}

int main(int argc, char *argv[])

{

subwidget sget;

const subwidget &wsget=sget;//非const对象可以赋给const 引用 

update(const_cast<subwidget*>(&wsget));//注意&wsget 需要加上括号,const_cast将const属性被转换掉 

widget *w=new subwidget();

// update(w); 错误 参数复制时,要复制的是子类,给的却是父类 

update1(new widget()); //可以自动向上转换 

return 0;

}

为何要去除const限定:如果我们不想修改const变量的值,那我们又为什么要去const呢?

原因是,我们可能调用了一个参数不是const的函数,而我们要传进去的实际参数确实const的,但是我们知道这个函数是不会对参数做修改的。于是我们就需要使用const_cast去除const限定,以便函数能够接受这个实际参数。

void Printer (int* val,string seperator = "\n")
{
	cout << val<< seperator;
}

int main(void) 
{	
	const int consatant = 20;
	//Printer(consatant);//Error: invalid conversion from 'int' to 'int*'
	Printer(const_cast<int *>(&consatant));
	
	return 0;
}
出现这种情况的原因,可能是我们所调用的方法是别人写的。还有一种我能想到的原因,是出现在const对象想调用自身的非const方法的时候。
我们定义了一个非const的变量,但用带const限定的指针去指向它,在某一处我们突然又想修改了,可是我们手上只有指针,这时候我们可以去const来修改了。

你可能感兴趣的:(static_const 和const_cast)