c++类型转换详解

c++ 类型转换

c++类型转换分为隐式类型转换和显式类型转换

一,隐式类型转换

又称为“标准转换”,包括以下几种情况:

1,算术转换(Arithmetic conversion) : 在混合类型的算术表达式中, 最宽的数据类型成为目标转换类型。
int ival = 3;
double dval = 3.14159;
ival + dval;//ival被提升为double类型
2,一种类型表达式赋值给另一种类型的对象:目标类型是被赋值对象的类型
int *pi = 0; // 0被转化为int *类型
ival = dval; // double->int

例外:void指针赋值给其他指定类型指针时,不存在标准转换,编译出错

3,将一个表达式作为实参传递给函数调用,此时形参和实参类型不一致:目标转换类型为形参的类型
extern double sqrt(double);
cout << "The square root of 2 is " << sqrt(2) << endl;
//2被提升为double类型:2.0
4,从一个函数返回一个表达式,表达式类型与返回类型不一致:目标转换类型为函数的返回类型
double difference(int ival1, int ival2)
{
    return ival1 - ival2;
    //返回值被提升为double类型
}

二,显式转换类型

被称为强制转换类型(cast

  • static__cast(expression)
  • dynamic__cast(expression)
  • reinterpret__cast(expression)
  • const__cast(expression)

1.static__cast(expression)


用于expression 和 new_type 之间的转换,前提条件是new_type和expression之间已经有了 混合的隐式转换( combination of implicit ) 或者 有自定义的转换类型 ( user-defined conversions )。
  • 基本数据类型的转换。
  • 类层次结构中基类和子类 向上转换(upcast)向下转换(downcast)
  • void指针转换为其他类型的指针(不安全的)
  • 任何类型转换为void类型
注意:
  • static_cast不能转换掉expresssion的 const , volitale , __unaligned 属性。

  • 在向下转换的过程中由于没有动态类型检查,所以也是不安全的。通常使用__dynamic____cast(expression)

sourse:test.cpp

#include <vector>
#include <iostream>

struct B {};
struct D : B {};

enum class E { ONE, TWO, THREE };
enum EU { ONE, TWO, THREE };

int main()
{
    // 1: initializing conversion
    /*int n = static_cast<int>(3.14); 
    std::cout << "n = " << n << '\n';
    std::vector<int> v = static_cast<std::vector<int>>(10); 
    //wrong no  combination of implicit or 
    std::cout << "v.size() = " << v.size() << '\n';*/
    std::vector<int> v(10);
    std::cout << "v.size() = " << v.size() << '\n';

    // 2: static downcast
    D d;
    B& br = d; // upcast via implicit conversion
    D& another_d = static_cast<D&>(br); // downcast

    // 3: lvalue to xvalue
    std::vector<int> v2 = static_cast<std::vector<int>&&>(v);
    std::cout << "after move, v.size() = " << v.size() << '\n';

    // 4: discarded-value expression
    static_cast<void>(v2.size());

    // 5. inverse of implicit conversion
    void* nv = &n;
    int* ni = static_cast<int*>(nv);
    std::cout << "*ni = " << *ni << '\n';

    // 6. array-to-pointer followed by upcast
    D a[10];
    B* dp = static_cast<B*>(a);

    // 7. scoped enum to int or float
    E e = E::ONE;
    int one = static_cast<int>(e);

    // 8. int to enum, enum to another enum
    E e2 = static_cast<E>(one);
    EU eu = static_cast<EU>(e2);

    // 9. pointer to member upcast
    // todo

    // 10. void* to any type
    void* voidp = &e;
    std::vector<int>* p = static_cast<std::vector<int>*>(voidp);
}

output:

n = 3
v.size() = 10
after move, v.size() = 0
*ni = 3

注意:

std::cout << "n = " << n << '\n';
std::vector<int> v = static_cast<std::vector<int> >(10); 

上段代码检查时会报错。因为没有定义或者实现的由int-to-vector 的转换。

2.dynamic__cast(expression)


通常用于继承关系中的安全的向上( upcast )或者向下( downcast )转换

newtype和expression 同为类指针,或者引用,安全转换。

sourse.cpp

#include <iostream>

struct V {
    virtual void f() {};  // must be polymorphic to use runtime-checked dynamic_cast
};
struct A : virtual V {};
struct B : virtual V {
    B(V* v, A* a) {
        // casts during construction (see the call in the constructor of D below)
        dynamic_cast<B*>(v); // well-defined: v of type V*, V base of B, results in B*
        dynamic_cast<B*>(a); // undefined behavior: a has type A*, A not a base of B
    }
};
struct D : A, B {
    D() : B((A*)this, this) { }
};

struct Base {
    virtual ~Base() {}
};

struct Derived: Base {
    virtual void name() {}
};

int main()
{
    D d; // the most derived object
    A& a = d; // upcast, dynamic_cast may be used, but unnecessary
    D& new_d = dynamic_cast<D&>(a); // downcast
    B& new_b = dynamic_cast<B&>(a); // sidecast


    Base* b1 = new Base;
    if(Derived* d = dynamic_cast<Derived*>(b1))
    {
        std::cout << "downcast from b1 to d successful\n";
        d->name(); // safe to call
    }

    Base* b2 = new Derived;
    if(Derived* d = dynamic_cast<Derived*>(b2))
    {
        std::cout << "downcast from b2 to d successful\n";
        d->name(); // safe to call
    }

    delete b1;
    delete b2;
}

output:

downcast from b2 to d successful

3.reinpreter__cast(expression)


reinpreter_cast可以把整数转换为指针或者指针转换为整数。以后研究。
#include <cstdint>
#include <cassert>
#include <iostream>
int f() { return 42; }
int main()
{
    int i = 7;

    // pointer to integer and back
    uintptr_t v1 = reinterpret_cast<uintptr_t>(&i); // static_cast is an error
    std::cout << "The value of &i is 0x" << std::hex << v1 << '\n';
    int* p1 = reinterpret_cast<int*>(v1);
    assert(p1 == &i);

    // pointer to function to another and back
    void(*fp1)() = reinterpret_cast<void(*)()>(f);
    // fp1(); undefined behavior
    int(*fp2)() = reinterpret_cast<int(*)()>(fp1);
    std::cout << std::dec << fp2() << '\n'; // safe

    // type aliasing through pointer
    char* p2 = reinterpret_cast<char*>(&i);
    if(p2[0] == '\x7')
        std::cout << "This system is little-endian\n";
    else
        std::cout << "This system is big-endian\n";

    // type aliasing through reference
    reinterpret_cast<unsigned int&>(i) = 42;
    std::cout << i << '\n';
}

output:

The value of &i is 0x7fff520e2a98
42
This system is little-endian
42

4.const__cast(expression)


该运算符对象用来修改类型的const或者volatile属性。常量类型转换为非常常量类。

sourse.cpp

#include <iostream>

struct type {
    type() :i(3) {}
    void m1(int v) const {
        // this->i = v;                 // compile error: this is a pointer to const
        const_cast<type*>(this)->i = v; // OK as long as the type object isn't const
    }
    int i;
};

int main() 
{
    int i = 3;                    // i is not declared const
    const int& cref_i = i; 
    const_cast<int&>(cref_i) = 4; // OK: modifies i
    std::cout << "i = " << i << '\n';

    type t; // note, if this is const type t;, then t.m1(4); is UB
    t.m1(4);
    std::cout << "type::i = " << t.i << '\n';

    const int j = 3; // j is declared const
    int* pj = const_cast<int*>(&j);
    *pj = 4;         // undefined behavior!

    void (type::*mfp)(int) const = &type::m1; // pointer to member function
//  const_cast<void(type::*)(int)>(mfp); // compiler error: const_cast does not
                                         // work on function pointers
}

output

i = 4
type::i = 4

三,总结

  • static__cast(expression) 简单暴力,通常用于标准类型转换,和有用户自定义的类型转换。
  • dynamic__cast(expression) 动态检查,安全的类型转换,通常用于继承关系中的转换。
  • reinterpret__cast(expression) 通常用于指针向整数,整数向指针的转换。
  • const__cast(expression) 通常用于改变变量的const或者volatile的属性。

熟练运用还需要在工程中掌握。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值