zoukankan      html  css  js  c++  java
  • C++的类型转换

    C++的类型转换

    类型转换4大金刚:

    • static_cast --- 执行基础转换
    • const_cast ---- (添加或者)移除 const
    • dynamic_cast ---- 执行已检查的多态转换,沿着继承层次结构安全地将指针和引用转换为向上、向下和横向的类
    • reinterpret_cast --- 执行一般的低级转换

    static_cast使用场景

    使用隐式转换和用户定义转换的组合在类型之间进行转换

    语法:
    static_cast < new_type > ( 表达式 )
    返回type的值new_type

    以下总结常使用static_cast的场景

    1. 初始化时转换

    //1.initializing conversion
    	int n = static_cast<int>(3.14159);
    	cout << "n = "<<n<<"
    "; //n=3
    
    	std::vector<int> v = static_cast<std::vector<int>>(10);
    	cout << "size of v is "<<v.size()<<"
    "; //10
    

    打印值在注释中,通过static_cast将某些类型做“静态”转变后成为我们希望的类型,并能正确初始化。

    2. static downcast

    struct B{
        static const int m = 0;
        void hello() const {
        	cout <<"hello ,this is B"<<"
    ";
        }
    };
    
    struct D:B
    {
        void hello() const{
        	cout << "hello,this is D"<<"
    ";
        }
    };
    
    //2. static downcast
        D d;
        B& br = d;
        br.hello(); //hello ,this is B
        D& anther_d = static_cast<D&>(br);
        anther_d.hello();//hello ,this is D
    
    

    br通过隐式类型转换后作为d的引用,虽然d是D类型的,但是调用的hello仍是B的hello函数,使用static_cast显式downcast后,调用D的hello。这里有一个问题是,hello并不是虚函数,即时D继承B,B和D都有一个hello,但是这里的hello函数并不是动态绑定的,仍在编译期绑定this的类型。因此br是B类型,而anther_d是D类型的(这里有疑问!!?)
    如果hello是虚函数,那么怎么解释呢?

    3. 隐式转换翻转

     	void* nv = &n;
        int* ni = static_cast<int*>(nv);
        std::cout << "*ni = " << *ni << '
    ';
    

    这算是static_cast 最常用的用法了,通过void指针将类型反转赋值。void可以通过static_cast转变为任意指针类型。

    4. enum类型转换

    enum E{ONE = 1,TWO,THREE};
    E e = E::ONE;
    int one = static_cast<int>(e);
    cout << "one : "<<one <<"
    ";
    

    const_cast使用场景

    1. 一般的const移除

    int i = 4;
    const int& rci = i ;
    const_cast<int&>(rci) = 8;
    
    const int j = 33;
    int*pj = const_cast<int*>(&j);
    //DO not use like below !
    // *pj = 333;
    // cout << "const int j = "<< j <<"
    ";
    

    2. 在类的const成员函数中:

    struct type{
        int i ;
    
        type() :i(3){}
        void f(int v) const{
    	//if we want to modify i 
    	//we cannot use this->i = v; directly;
    	//becuse this pointer is const ,
    	//we shall use const_cast this pointer
    	const_cast<type*>(this)->i = v;
        }
    };
    
    type t;
    t.f(40) ;
    cout << "type i = "<<t.i <<"
    ";
    
    

    使用const修饰的成员函数,我们将无法通过this指针,修改其成员变量,因为我们可以将this指针使用const_cast转换为non-const的,只是,你真的确定要这么做么?!

    dynamic_cast 使用场景

    必须是多态场景,存在基类与派生类的类型转换;如果转换成功,dynamic_cast返回类型为new_type的值。如果转换失败,而new_type是指针类型,则返回该类型的空指针。如果转换失败,并且new_type是引用类型,它将抛出一个异常,该异常与类型std::bad_cast的处理程序匹配。

    struct Base {
        virtual ~Base() {}
    };
     
    struct Derived: Base {
        virtual void name() {}
    };
    
    void testDynamic_cast()
    {
        Base *b1 = new Base;
        if(Derived*d = dynamic_cast<Derived*>(b1)){
            cout << "downcast from b1 to d successful
    ";
            d->name();
        }
    
        Base *b2 = new Derived;
        if(Derived*d = dynamic_cast<Derived*>(b2)){
            cout << "downcast from b2 to d successful
    ";
            d->name();
        }
    
        delete b1;
        delete b2;
    }
    

    输出
    downcast from b2 to d successful

    可见b1的dynamic_cast转换是失败的。原因是显而易见的 ,此时的b1指针并没有指向其派生类,自然不能进行动态转换。但是,在C类型的转换中,这样的转换是没有任何提示和预见性的,所以,C类型的转换应该被全线禁止掉。

    reinterpret_cast的使用场景

    标准文档上的解释是:通过重新解释底层位模式在类型之间进行转换

    与static_cast不同,但与const_cast相似,reinterpret_cast表达式不会编译成任何CPU指令(除非在整数和指针之间进行转换,或者在指针表示依赖于其类型的模糊架构上进行转换)。

    它纯粹是一个编译时指令,指示编译器将表达式视为具有new_type类型

    unsigned int i = 0x12345678;
    
    char* p1 = reinterpret_cast<char*>(&i);
    if(p1[0] == 'x78')
    	cout << "This system is little-endian
    ";
    else 
    	cout << "This system is big-endian
    ";
    

    p1指针将i的地址重现解释为char*类型。这里顺便复习下大小端的知识,78是i的低字节位,如果它位于unsigned int内存的低地址区域则说明系统为小端,否则为大端。

    以上,说明了四种C++类型转换表达式的使用场景,按我个人理解小结下:

    • 如果希望在内存指针层面对指针重新解释,也是就让编译器认为这个指针是某个类型,则需要使用reinterpret_cast,
    • 如果涉及到基类和派生类指针的动态转换,则使用dynamic_cast;
    • 如果需要移除const属性,则需要使用const_cast;
    • 其余情况就使用static_cast吧。
  • 相关阅读:
    感知机简单算法的实现
    C语言博客作业02
    我的第二次C语言作业
    [原]wpf foundation Part 1 of n (object resource )
    [orginal]TabControlView based on css ,js and html .
    [orginal]checkBox based on web(thinking in & implementation)
    [orginal] Progressbar implementation with js,css,and html
    [orginal]Combolist visual design & and implementation ( based on css ,js and html)
    [orginal] nice look ListBox with powerful methodes designing & implementation based on web technology.
    [orginal]treeView control based on WEB
  • 原文地址:https://www.cnblogs.com/Stultz-Lee/p/10089087.html
Copyright © 2011-2022 走看看