const_cast<new_type>(expression):
直接看demo吧:
#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()
{
//case 1:
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';
//case 2:
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';
//case 3:
const int j = 3; // j is declared const
int* pj = const_cast<int*>(&j);
*pj = 4; // undefined behavior!
//case 4:
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
}
static_cast<new_type>(expression): 返回一个new_type类型的值.
1,Notice: 此时的new_type是既不是指针(pointer)也不是任何引用(reference)的情况.
如果 expression 和 new_type之间存在一个隐式(implicit)的转换关系(比如: int->double, short int->int..., 甚至是如果一个类类型(class)含有operator Type()我们都能完成从 expression 到 new_type的转换,或者是一个class含有一个implicit的构造函数此时我们相当于用expression构造该class),转换后返回的是一个 new_type类型的右值(rvalue).
2,如果class D 是 class E的虚基类 那么此时不能进行static_cast, 如果class D是 class E的pure-base-class此时也不能进行static_cast. 另外由于static_cast是编译时会生成额外代码的所以最好不要使用static_cast来进行多态下的upcast和downcast, 且在cast过程中static_cast是不检查当前两个类型是否是位于同一继承体系的. 但是如果想要实现 static polymorphism 的话是可以使用static_cast的, 其他情况下最好老老实实使用dynamic_cast.
3,Notice: 此时的new_type是一个右值引用类型(比如:int&&, std::vector<int>&&),此时expression可以是左值可以是右值.
当把一个lvalue(左值)转为右值(rvalue)的时候其实相当于对expression调用了std::move;
4,Notice: 此时的new_type为void;
当我们有一个不用的参数的时候编译器会经过就可以调用static_cast<void>(expression);消除编译器警告.
5,Notice: 取回存于void*指针的,原类型的指针.
6,Notice: 此时new_type为enum类型.
把一个enum(不管有没有指定class)类型的值转为它的underlying-type;
把一个指定了class的enum的类型转为一个没有指定class的enum类型.
7,如果一个指针指向派生类的成员(不管是数据成员,还是成员函数),且该成员是通过继承得到的也就是说该成员其实是基类中的那么我们可以通过static_cast,把该指针转为指向基类的该成员的指针.
8,指向任何类型的指针都能转为 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: initializing conversion
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: static downcast
D d;
B& br = d; // upcast via implicit conversion
br.hello();
D& another_d = static_cast<D&>(br); // downcast
another_d.hello();
// 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);
std::cout << one << '\n';
// 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
int D::*pm = &D::m;
std::cout << br.*static_cast<int B::*>(pm) << '\n';
// 10. void* to any type
void* voidp = &e;
std::vector<int>* p = static_cast<std::vector<int>*>(voidp);
}