c++ 类型转换
c++类型转换分为隐式类型转换和显式类型转换
一,隐式类型转换
又称为“标准转换”,包括以下几种情况:
1,算术转换(Arithmetic conversion) : 在混合类型的算术表达式中, 最宽的数据类型成为目标转换类型。
int ival = 3;
double dval = 3.14159;
ival + dval;//ival被提升为double类型
2,一种类型表达式赋值给另一种类型的对象:目标类型是被赋值对象的类型
int *pi = 0; // 0被转化为int *类型
ival = dval; // double->int
例外:void指针赋值给其他指定类型指针时,不存在标准转换,编译出错
3,将一个表达式作为实参传递给函数调用,此时形参和实参类型不一致:目标转换类型为形参的类型
extern double sqrt(double);
cout << "The square root of 2 is " << sqrt(2) << endl;
//2被提升为double类型:2.0
4,从一个函数返回一个表达式,表达式类型与返回类型不一致:目标转换类型为函数的返回类型
double difference(int ival1, int ival2)
{
return ival1 - ival2;
//返回值被提升为double类型
}
二,显式转换类型
被称为强制转换类型(cast)
- static__cast(expression)
- dynamic__cast(expression)
- reinterpret__cast(expression)
- const__cast(expression)
1.static__cast(expression)
用于expression 和 new_type 之间的转换,前提条件是new_type和expression之间已经有了 混合的隐式转换( combination of implicit ) 或者 有自定义的转换类型 ( user-defined conversions )。
- 基本数据类型的转换。
- 类层次结构中基类和子类 向上转换(upcast) 和 向下转换(downcast)
- void指针转换为其他类型的指针(不安全的)
- 任何类型转换为void类型
注意:
static_cast不能转换掉expresssion的 const , volitale , __unaligned 属性。
在向下转换的过程中由于没有动态类型检查,所以也是不安全的。通常使用__dynamic____cast(expression)
sourse:test.cpp
#include <vector>
#include <iostream>
struct B {};
struct D : B {};
enum class E { ONE, TWO, THREE };
enum EU { ONE, 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);
//wrong no combination of implicit or
std::cout << "v.size() = " << v.size() << '\n';*/
std::vector<int> v(10);
std::cout << "v.size() = " << v.size() << '\n';
// 2: static downcast
D d;
B& br = d; // upcast via implicit conversion
D& another_d = static_cast<D&>(br); // downcast
// 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);
// 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
// todo
// 10. void* to any type
void* voidp = &e;
std::vector<int>* p = static_cast<std::vector<int>*>(voidp);
}
output:
n = 3
v.size() = 10
after move, v.size() = 0
*ni = 3
注意:
std::cout << "n = " << n << '\n';
std::vector<int> v = static_cast<std::vector<int> >(10);
上段代码检查时会报错。因为没有定义或者实现的由int-to-vector 的转换。
2.dynamic__cast(expression)
通常用于继承关系中的安全的向上( upcast )或者向下( downcast )转换
newtype和expression 同为类指针,或者引用,安全转换。
sourse.cpp
#include <iostream>
struct V {
virtual void f() {}; // must be polymorphic to use runtime-checked dynamic_cast
};
struct A : virtual V {};
struct B : virtual V {
B(V* v, A* a) {
// casts during construction (see the call in the constructor of D below)
dynamic_cast<B*>(v); // well-defined: v of type V*, V base of B, results in B*
dynamic_cast<B*>(a); // undefined behavior: a has type A*, A not a base of B
}
};
struct D : A, B {
D() : B((A*)this, this) { }
};
struct Base {
virtual ~Base() {}
};
struct Derived: Base {
virtual void name() {}
};
int main()
{
D d; // the most derived object
A& a = d; // upcast, dynamic_cast may be used, but unnecessary
D& new_d = dynamic_cast<D&>(a); // downcast
B& new_b = dynamic_cast<B&>(a); // sidecast
Base* b1 = new Base;
if(Derived* d = dynamic_cast<Derived*>(b1))
{
std::cout << "downcast from b1 to d successful\n";
d->name(); // safe to call
}
Base* b2 = new Derived;
if(Derived* d = dynamic_cast<Derived*>(b2))
{
std::cout << "downcast from b2 to d successful\n";
d->name(); // safe to call
}
delete b1;
delete b2;
}
output:
downcast from b2 to d successful
3.reinpreter__cast(expression)
reinpreter_cast可以把整数转换为指针或者指针转换为整数。以后研究。
#include <cstdint>
#include <cassert>
#include <iostream>
int f() { return 42; }
int main()
{
int i = 7;
// pointer to integer and back
uintptr_t v1 = reinterpret_cast<uintptr_t>(&i); // static_cast is an error
std::cout << "The value of &i is 0x" << std::hex << v1 << '\n';
int* p1 = reinterpret_cast<int*>(v1);
assert(p1 == &i);
// pointer to function to another and back
void(*fp1)() = reinterpret_cast<void(*)()>(f);
// fp1(); undefined behavior
int(*fp2)() = reinterpret_cast<int(*)()>(fp1);
std::cout << std::dec << fp2() << '\n'; // safe
// type aliasing through pointer
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";
// type aliasing through reference
reinterpret_cast<unsigned int&>(i) = 42;
std::cout << i << '\n';
}
output:
The value of &i is 0x7fff520e2a98
42
This system is little-endian
42
4.const__cast(expression)
该运算符对象用来修改类型的const或者volatile属性。常量类型转换为非常常量类。
sourse.cpp
#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()
{
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';
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 is declared const
int* pj = const_cast<int*>(&j);
*pj = 4; // undefined behavior!
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
}
output
i = 4
type::i = 4
三,总结
- static__cast(expression) 简单暴力,通常用于标准类型转换,和有用户自定义的类型转换。
- dynamic__cast(expression) 动态检查,安全的类型转换,通常用于继承关系中的转换。
- reinterpret__cast(expression) 通常用于指针向整数,整数向指针的转换。
- const__cast(expression) 通常用于改变变量的const或者volatile的属性。
熟练运用还需要在工程中掌握。