C++字符串类型繁多,如std::string、char、wchar_t等
强制转换
static_cast
、dynamic_cast
、const_cast
、reinterpret_cast
四种转换符,语法:*_cast<新类型>(表达式)
简单地说:
static_cast
适用于允许(隐式)转换的场合,明确告知编译器转换合法dynamic_cast
适用于有继承层级的转换const_cast
适用于常量与非常量的转换reinterpret_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(const
与volatile
)限定的类型间转换
函数指针和成员函数指针不可用于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 起)