C++常用转换

oneNeko 于 2022-04-19 发布

C++字符串类型繁多,如std::string、char、wchar_t

强制转换

static_castdynamic_castconst_castreinterpret_cast四种转换符,语法:*_cast<新类型>(表达式)

简单地说:

static_cast

用隐式和用户定义转换的组合在类型间转换。

#include <vector>
#include <iostream>

struct B {
    int m = 0;
    void hello() const {
        std::cout << "Hello world, this is B!\n";
    }
};
struct D : B {
    void hello() const {
        std::cout << "Hello world, this is D!\n";
    }
};

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

int main()
{
    // 1: 初始化转换
    int n = static_cast<int>(3.14);
    std::cout << "n = " << n << '\n';
    std::vector<int> v = static_cast<std::vector<int>>(10);
    std::cout << "v.size() = " << v.size() << '\n';

    // 2: 静态向下转型
    D d;
    B& br = d; // 通过隐式转换向上转型
    br.hello();
    D& another_d = static_cast<D&>(br); // 向下转型
    another_d.hello();

    // 3: 左值到右值
    std::vector<int> v2 = static_cast<std::vector<int>&&>(v);
    std::cout << "after move, v.size() = " << v.size() << '\n';

    // 4: 弃值表达式
    static_cast<void>(v2.size());

    // 5. 隐式转换的逆
    void* nv = &n;
    int* ni = static_cast<int*>(nv);
    std::cout << "*ni = " << *ni << '\n';

    // 6. 数组到指针后随向上转型
    D a[10];
    B* dp = static_cast<B*>(a);

    // 7. 有作用域枚举到 int 或 float
    E e = E::ONE;
    int one = static_cast<int>(e);
    std::cout << one << '\n';

    // 8. int 到枚举,枚举到另一枚举
    E e2 = static_cast<E>(one);
    EU eu = static_cast<EU>(e2);

    // 9. 指向成员指针向上转型
    int D::* pm = &D::m;
    std::cout << br.*static_cast<int B::*>(pm) << '\n';

    // 10. void* 到任何类型
    void* voidp = &e;
    std::vector<int>* p = static_cast<std::vector<int>*>(voidp);
}

dynamic_cast

沿继承层级向上、向下及侧向,安全地转换到其他类的指针和引用。

#include <iostream>
 
struct V {
    virtual void f() {}  // 必须为多态以使用运行时检查的 dynamic_cast
};
struct A : virtual V {};
struct B : virtual V {
  B(V* v, A* a) {
    // 构造中转型(见后述 D 的构造函数中的调用)
    dynamic_cast<B*>(v); // 良好定义:v 有类型 V*,B 的 V 基类,产生 B*
    dynamic_cast<B*>(a); // 未定义行为:a 有类型 A*,A 非 B 的基类
  }
};
struct D : A, B {
    D() : B((A*)this, this) { }
};
 
struct Base {
    virtual ~Base() {}
};
 
struct Derived: Base {
    virtual void name() {}
};
 
int main()
{
    D d; // 最终派生对象
    A& a = d; // 向上转型,可以用 dynamic_cast,但不必须
    D& new_d = dynamic_cast<D&>(a); // 向下转型
    B& new_b = dynamic_cast<B&>(a); // 侧向转型
 
 
    Base* b1 = new Base;
    if(Derived* d = dynamic_cast<Derived*>(b1))
    {
        std::cout << "downcast from b1 to d successful\n";
        d->name(); // 可以安全调用
    }
 
    Base* b2 = new Derived;
    if(Derived* d = dynamic_cast<Derived*>(b2))
    {
        std::cout << "downcast from b2 to d successful\n";
        d->name(); // 可以安全调用
    }
 
    delete b1;
    delete b2;
}

const_cast

在有不同cv(constvolatile)限定的类型间转换

函数指针和成员函数指针不可用于const_cast

int main() {

	const char* c_str1 = "12345";
	char* str1 = const_cast<char*>(c_str1);
	const char* c_str2 = const_cast<const char*>(str1);

	return 0;
}

reinterpret_cast

转换类型到无关类型.它纯粹是一个编译时指令,指示编译器将表达式视为如同具有新类型类型一样处理。除非十分明确转换不会出问题,否则不要使用这个转换

C风格转换

用显式和隐式转换的组合进行类型之间的转换。

( 新类型 ) 表达式	(1)	
新类型 ( 表达式 )	(2)	
新类型 ( 表达式列表 )	(3)	
新类型 ( )	(4)	
新类型 { 表达式列表(可选) }	(5)	(C++11 起)
模板名 ( 表达式列表(可选) )	(6)	(C++17 起)
模板名 { 表达式列表(可选) }	(7)	(C++17 起)

参考

C++ 表达式