const_cast 根据 http://www.cplusplus.com 的说法,const_cast用于对象指针或引用的const的添加和删除操作
例子如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #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 ; }
输出为
http://en.cppreference.com 上有更多的信息
函数指针和成员函数指针不可用于const_cast
const_cast可以使实际指代const对象的到非const类型的引用或指针,但是通过非const访问路径修改const对象则是未定义行为。
更详细的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <iostream> struct type { type () :i (3 ) {} void m1 (int v) const { const_cast <type*>(this )->i = v; } int i; }; int main () { int i = 3 ; const int & cref_i = i; const_cast <int &>(cref_i) = 4 ; std::cout << "i = " << i << '\n' ; type t; t.m1 (4 ); std::cout << "type::i = " << t.i << '\n' ; const int j = 3 ; int * pj = const_cast <int *>(&j); void (type::*mfp)(int ) const = &type::m1; }
输出
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的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include <cstdint> #include <cassert> #include <iostream> int f () { return 42 ; }int main () { int i = 7 ; uintptr_t v1 = reinterpret_cast <uintptr_t >(&i); 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); 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; }
输出
1 2 3 4 The value of &i is 0 x7 fff352 c3580 42 This system is little-endian42
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,求值后舍弃该值
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 #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 () { 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' ; D d; B& br = d; br.hello (); D& another_d = static_cast <D&>(br); another_d.hello (); std::vector<int > v2 = static_cast <std::vector<int >&&>(v); std::cout << "after move, v.size() = " << v.size () << '\n' ; static_cast <void >(v2.size ()); void * nv = &n; int * ni = static_cast <int *>(nv); std::cout << "*ni = " << *ni << '\n' ; D a[10 ]; B* dp = static_cast <B*>(a); E e = E::ONE; int one = static_cast <int >(e); std::cout << one << '\n' ; E e2 = static_cast <E>(one); EU eu = static_cast <EU>(e2); int D::*pm = &D::m; std::cout << br.*static_cast <int B::*>(pm) << '\n' ; void * voidp = &e; std::vector<int >* p = static_cast <std::vector<int >*>(voidp); }
输出
1 2 3 4 5 6 7 8 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 *的指针、引用转换,同时必须为多态以使用运行时检查的
例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 #include <iostream> struct V { virtual void f () {}; };struct A : virtual V {};struct B : virtual V { B (V* v, A* a) { dynamic_cast <B*>(v); dynamic_cast <B*>(a); } };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; 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; }
输出
1 downcast from b2 to d successful
dynamic_cast与static_cast在类转换上的不同在于,dynamic_cast会确保转化成功,在转化不成功时会设置为NULL,如上例中
1 Derived* d = dynamic_cast <Derived*>(b1)