zoukankan      html  css  js  c++  java
  • C++标准转换运算符static_cast

    static_cast <new_type> (expression)

    虽然const_cast是用来去除变量的const限定,但是static_cast却不是用来去除变量的static引用。其实这是很容易理解的,static决定的是一个变量的作用域和生命周期,比如:在一个文件中将变量定义为static,则说明这个变量只能在本Package中使用;在方法中定义一个static变量,该变量在程序开始存在直到程序结束;类中定义一个static成员,该成员随类的第一个对象出现时出现,并且可以被该类的所有对象所使用。

    对static限定的改变必然会造成范围性的影响,而const限定的只是变量或对象自身。但无论是哪一个限定,它们都是在变量一出生(完成编译的时候)就决定了变量的特性,所以实际上都是不容许改变的。这点在const_cast那部分就已经有体现出来。

    static_cast和reinterpret_cast一样,在面对const的时候都无能为力:两者都不能去除const限定。两者也存在的很多的不同,比如static_cast不仅可以用在指针和引用上,还可以用在基础数据和对象上;前面提到过reinterpret_cast可以用在"没有关系"的类型之间,而用static_cast来处理的转换就需要两者具有"一定的关系"了。

    还是用例子来说明比较直观一些。

    还是用例子来说明比较直观一些。

    reinterpret_cast一篇,已经提到过reinterpret_cast可以在任意指针之间进行互相转换,即使这些指针所指的内容是毫无关系的,也就是说一下语句,编译器是不会报错的,但是对于程序来说也是毫无意义可言的,只会造成程序崩溃:

    
    #include <iostream>
    using namespace std;
    unsigned short Hash( void *p ) {
    	unsigned long val = reinterpret_cast<unsigned long>( p );
    	return ( unsigned short )( val ^ (val >> 16));
    }
    
    class Something
    {
    	/* Some codes here */
    };
    
    class Otherthing
    {
    	/* Some codes here */
    };
    
    int main() {
    	
    	typedef unsigned short (*FuncPointer)( void *) ;
    	FuncPointer fp = Hash;	//right, this is what we want
    
    	int a[10];
    	const int* ch = a; //right, array is just like pointer
    	char chArray[4] = {'a','b','c','d'};
    	fp = reinterpret_cast<FuncPointer> (ch); //no error, but does not make sense
    	ch = reinterpret_cast<int*> (chArray);	//no error
    	
    	cout <<hex<< *ch;	//output: 64636261	//it really reinterpret the pointer
    
    	
    	Something * st = new Something();
    	Otherthing * ot = reinterpret_cast<Otherthing*> (st); //cast between objects with on relationship
    }
    
    

    而以上转换,都是static_cast所不能完成的任务,也就是说把上边程序里所有的reinterpret_cast换成static_cast的话,就会立即得到编译错误,因为目标指针和原始指针之间不存在"关系"

    从上边的程序,也就一下子看出来了reinterpret_cast和static_cast之间最本质的区别。

    而以上转换,都是static_cast所不能完成的任务,也就是说把上边程序里所有的reinterpret_cast换成static_cast的话,就会立即得到编译错误,因为目标指针和原始指针之间不存在"关系"

    从上边的程序,也就一下子看出来了reinterpret_cast和static_cast之间最本质的区别。

    对于static_cast所需要的关系,"继承"绝对是其中之一,所以static_cast支持指向基类的指针和指向子类的指针之间的互相转换:

    
    class Parents
    {
    public:
    	virtual ~Parents(){}
    	/*codes here*/
    };
    
    class Children : public Parents
    {
    	/*codes here*/
    };
    
    int main() 
    {	
    	Children * daughter = new Children();
    	Parents * mother = static_cast<Parents*> (daughter); //right, cast with polymorphism
    	
    	Parents * father = new Parents();
    	Children * son = static_cast<Children*> (father); //no error, but not safe
    }
    
    

    但是从基类到子类的转换,用static_cast并不是安全的,具体的问题会在dynamic_cast一篇阐述。

    在指针和引用方便,似乎也只有继承关系是可以被static_cast接受的,其他情况的指针和引用转换都会被static_cast直接扔出编译错误,而这层关系上的转换又几乎都可以被dynamic_cast所代替。这样看起来static_cast运算符的作用就太小了。

    实际上static_cast真正用处并不在指针和引用上,而在基础类型和对象的转换上 。 而基于基础类型和对象的转换都是其他三个转换运算符所办不到的。

    这些转换跟C++用户自定义类型转换一文中所设计的内容比较接近,所以在那边文章中出现转换可以全部加上static_cast。

    基础类型转换:
    float floatValue = 21.7;
    int intValue = 7;

    cout << floatValue / 7 << "\t\t" << static_cast<int> (floatValue)/7 <<endl;
    cout << intValue/3 << "\t\t" << static_cast<double> (intValue)/3 << endl;

    //Output:
    //3.1     3
    //2       2.33333

    从输出结果可以看出转换是成功并且正确的。

    对于对象的转换,也是需要又关系的,这层关系就是C++用户自定义类型转换中提到的方法:

    • 构造函数(Constructor)
    • 类型转换运算符(Type –Cast Operator

    static_cast会根据上述顺序寻找到合适的方法进行类型转换。

    赋值运算符并不被算在内,因为它自身已经是一种运算符,不能再当做转换运算符来用。

    
    int main(void) 
    {
    	Ape a;
     	Human h = static_cast<Human> (a); // using promtion constructor
    
    	Programmer p;
    	p = static_cast<Programmer> (h); // using  Programmer-cast operaotor
    
    	//Ape a2;
    	//a2 = static_cast<Ape> (p); //Error, assignment operator should be used directly
    
    	return 0;
    }
    
    

    (类的代码见C++用户自定义类型转换,或者下载代码查看)

    传统转换方式实现static_cast运算符

    从上边对static_cast分析可以跟看,static_cast跟传统转换方式几乎是一致的,所以只要将static_cast和圆括号去掉,再将尖括号改成圆括号就变成了传统的显示转换方式。在C++用户自定义类型转换一文已有很多的介绍了。

  • 相关阅读:
    iOS resign code with App Store profile and post to AppStore
    HTTPS科普扫盲帖 对称加密 非对称加密
    appid 评价
    使用Carthage安装第三方Swift库
    AngularJS:何时应该使用Directive、Controller、Service?
    xcode7 The operation couldn't be completed.
    cocoapods pod install 安装报错 is not used in any concrete target
    xcode7 NSAppTransportSecurity
    learning uboot how to set ddr parameter in qca4531 cpu
    learning uboot enable protect console
  • 原文地址:https://www.cnblogs.com/ider/p/cpp_cast_operator_part4.html
Copyright © 2011-2022 走看看