C++类型转化表达式小结
2017-09-14 18:18
316 查看
const_cast
根据http://www.cplusplus.com的说法,const_cast用于对象指针或引用的const的添加和删除操作例子如下:
// const_cast #include <iostream> using namespace std; void print (char * str) { cout << str << '\n'; } int main () { const char * c = "sample text"; print ( const_cast<char *> (c) ); return 0; }
输出为
sample text
http://en.cppreference.com上有更多的信息
函数指针和成员函数指针不可用于const_cast
const_cast可以使实际指代const对象的到非const类型的引用或指针,但是通过非const访问路径修改const对象则是未定义行为。
更详细的例子
#include <iostream> struct type { type() :i(3) {} void m1(int v) const { // this->i = v; // 编译错误:这是指向 const 的指针 const_cast<type*>(this)->i = v; // 只要对象不是 const 就 OK } int i; }; int main() { int i = 3; // i 不声明为 const const int& cref_i = i; const_cast<int&>(cref_i) = 4; // OK :修改 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 声明为 const int* pj = const_cast<int*>(&j); // *pj = 4; // 未定义行为! void (type::*mfp)(int) const = &type::m1; // 指向成员函数指针 // const_cast<void(type::*)(int)>(mfp); // 编译错误: const_cast 对函数指针不起作用 }
输出
i = 4 type::i = 4
reinterpret_cast
reinterpret_cast可以在任意类型指针进行转换,哪怕是不相关的类型。还可用于指针或引用与整型的相互转化,不单是int,还包括short、long等整数类型。
原因在于reinterpret_cast是“simple binary copy”,cplusplus的原话是“The operation result is a simple binary copy of the value from one pointer to the other. All pointer conversions are allowed: neither the content pointed nor the pointer type itself is checked.”
经过测试,整型与char *之间的转化也可以正常进行
cppreference的例子
#include <cstdint> #include <cassert> #include <iostream> int f() { return 42; } int main() { int i = 7; // 指针到整数并转回 uintptr_t v1 = reinterpret_cast<uintptr_t>(&i); // static_cast 为错误 std::cout << "The value of &i is 0x" << std::hex << v1 << '\n'; int* p1 = reinterpret_cast<int*>(v1); assert(p1 == &i); // 到另一函数指针并转回 void(*fp1)() = reinterpret_cast<void(*)()>(f); // fp1(); 未定义行为 int(*fp2)() = reinterpret_cast<int(*)()>(fp1); std::cout << std::dec << fp2() << '\n'; // 安全 // 通过指针的类型别名使用 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"; // 通过引用的类型别名使用 reinterpret_cast<unsigned int&>(i) = 42; std::cout << i << '\n'; const int &const_iref = i; // int &iref = reinterpret_cast<int&>(const_iref); // 编译错误——不能去除 const // 必须用 const_cast 代替: int &iref = const_cast<int&>(const_iref); }
输出
The value of &i is 0x7fff352c3580 42 This system is little-endian 42
static_cast
static_cast可以在有联系的类型之间进行指针转换(between pointers to related classes),不但包括派生类转换基类,也包括基类转换派生类。static_cast还可以完成以下两种
Convert from void* to any pointer type.可以有void *到任何类型
Convert integers, floating-point values and enum types to enum types.由整数、浮点、枚举值到枚举值
此外
Explicitly call a single-argument constructor or a conversion operator. 调用单一参数的构造函数或转换的重载符号
Convert to rvalue references. (由左值)转化成右值的引用
Convert enum class values into integers or floating-point values. 枚举类转化为整数、浮点数
Convert any type to void, evaluating and discarding the value. 任意类型到void,求值后舍弃该值
示例
#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); }
输出
n = 3 v.size() = 10 Hello world, this is B! Hello world, this is D! after move, v.size() = 0 *ni = 3 1 0
dynamic_cast
dynamic_cast只能用于类或者void *的指针、引用转换,同时必须为多态以使用运行时检查的例子
#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; }
输出
downcast from b2 to d successful
dynamic_cast与static_cast在类转换上的不同在于,dynamic_cast会确保转化成功,在转化不成功时会设置为NULL,如上例中
Derived* d = dynamic_cast<Derived*>(b1)
相关文章推荐
- C++类型转化小结
- C++中的数组array和vector,lambda表达式,C字符串加操作,C++中新类型数组(数组缓存),多元数组,new缓冲
- java基础改学C++(一)数据类型与表达式
- C++中string转化为常用数值类型
- C/C++ 字符串与数字相互转化方法小结
- c与c++中一些类型的转化总结(持续更新)
- JavaScript核心语法————数据类型转化、运算符、表达式
- 数据类型和表达式(c++)
- C++ 学习之构造函数:构造函数小结3 默认构造函数、隐式类型转换和复制构造函数
- c++类型转化
- C++ int与string类型相互转化
- 如何把SEH类型的系统异常转化为C++类型的异常
- C++:数据类型和表达式<1>无符号和有符号整型
- C++类型转化分析:强制转换,动态转换,静态转换等。
- C++ 转换类型运算符 调用构造函数将变量转化成为一个对象的成员变量
- C++学习笔记:const_cast类型转化
- C++ 的4种类型转化方法
- c++中类型的转化
- C++数据类型转换小结
- C++--四种类型转化杂记,学习代码