一、算数转换
算术转换(Arithmetic conversions):在算术运算中,如果操作数为整数类型,会进行整数提升(Integral promotion),将较小的类型值提升为int类型(或者unsigned int,如果较小的类型是unsigned类型),然后进行运算;
int a = 5.2;
cout << a;//输出5
float b = 515.2;
long long c=1023546987412;
cout << a + b + c << endl;//输出的类型是longlong类型
二、强制转换
(转换的类型)数据
cout << 5 / 2 << endl;//输出2
cout << (double)5 / 2 << endl;//输出2.5
cout << (double)(5 / 2) << endl;//输出2
三、类的强制类型转换
- 一个类可以有多个转换函数。
- 多个参数的构造函数,除第一个参数外,如果其它参数都有缺省值,也可以作为转换函数。
- Person(int)的隐式转换的场景:←
- 将 Person对象初始化为 int 值时。
- 将 int 值传递给接受Person参数的函数时。←
- 返回值被声明为 Person的函数试图返回 int 值时。
- 在上述任意一种情况下,使用可转换为int,类型的内置类型时
#include<iostream>
using namespace std;
class Person {
public:
int c_age;
string c_name;
float c_weight;
Person(int age) :c_age(age),c_name("NULL"),c_weight(0) {
cout << "调用了Person(int age)" << endl;
}
Person() :c_age(0), c_name("NULL"), c_weight(0) {
cout << "调用了Person()" << endl;
}
};
ostream& operator<<(ostream& cout, const Person& p){
cout << "--->c_age: " << p.c_age << endl;
cout << "--->c_name: " << p.c_name << endl;
cout << "--->c_weight: " << p.c_weight << endl;
cout << endl << endl;
return cout;
}
void show(const Person& p){
cout << p;
}
Person say(){
return 5;
}
int main() {
Person p1(20);//常规写法
cout << p1;
Person p2 = 10;//隐式转换,将Person对象初始化为 int 值时。
cout << p2;
Person p3 = Person(15);//显式转换
cout << p3;
//将 int 值传递给接受Person参数的函数时。
show(25);
//返回值被声明为 Person的函数试图返回int值时。
say();
return 0;
}
将构造函数用作自动类型转换函数似乎是一项不错的特性,但有时候会导致意外的类型转换。explicit 关键字用于关闭这种自动特性,但仍允许显示转换。“
在实际开发中,如果强调的是构造,建议使用 explicit,如果强调的是类型转换,则不使用explici
explicit Person(int age);
Person p1=8;// 错误。
Person p2=Person(8); // 显示转换,可以。
Person p3=(Person)8; // 显示转换,可以。
四、static_cast
static_cast的定义为:static_cast<type_name>(expression)
type_name是转换的类型,expression是被转换的对象或者表达式。static_cast一般用于隐式转换,当type_name和express至少有一方可以隐式转换时,则可以用static进行强制类型转换。可以用于常见的int、float、double等类型转换;转换成功返回true,否则返回false(相当于C语言中的强制类型转换)。这样转换是不安全的,因为派生类的成员在基类中不一定存在。
#include<iostream>
#include <vector>
using namespace std;
class Person {
public:
void func()const {
cout << "hello i'm Person" << endl;
}
};
class Child:public Person {
public:
void func()const {
cout << "hello i'm Child" << endl;
}
};
int main() {
//普通类型转换
double a = 13.14;
cout << a << endl;//输出13.14
int b = static_cast<int>(a);
cout << b << endl;//输出13
//父类到子类的转化
Person* p1 = new Person();
p1->func();
Child* p2 = static_cast<Child*>(p1);
p2->func();
return 0;
}
如果在派生类中添加一个成员age,因为在基类中没有成员age所以在使用static_cast转换的时候是不安全的会输出错误乱码
class Child:public Person {
public:
int age = 20;
void func()const {
cout << "hello i'm Child. And i'm "<<age<<" years old!" << endl;
}
};
五、dynamic_cast
dynamic_cast的定义为:dynamic_cast<type_name>(expression)
type_name是转换的类型,expression是被转换的对象或者表达式。dynamic一般用于基类指向派生类时的强制转换,转换成功返回true,失败返回false。它不像static_cast一样向下转换不安全,它是安全的。
具体可以看这篇文章C++新特性08_强制转换dynamic_cast
六、const_cast
定义为const_cast<type_name>(expression)
type_name是转换的类型,expression是被转换的对象或者表达式。const_case有两个功能,分别是去掉const和加上const,一般用于去掉const,修改被const修饰为常量的值。但是修改的这个值本身不能是const常量,而是被二次引用或者传参数时被引用为const,才能修改,否则修改失败。同时type和express两个类型要一直去掉const,修改成功返回true,否则返回false。
int main() {
int* a = new int(2);
const int* serven_int_5 = const_cast<const int*>(a); // 转换为常量指针
*a = 3;
*serven_int_5 = 4; // 不能修改
return 0;
}
七、reinterpret_cast
reinterpret_cast的定义为:reinterpret_cast<type_name>(expression)
type_name是转换的类型,expression是被转换的对象或者表达式。
reinterpret_cast将double类型转换成int,再转换成double类型后精度不会丢失,而static_cast会丢失。
int main() {
double a = 13.14;
char* b = reinterpret_cast<char*>(&a);
double* c = reinterpret_cast<double*>(b);
cout << *c << endl;
int* d = reinterpret_cast<int*>(&a);
double* e = reinterpret_cast<double*>(d);
cout << *e<< endl;
return 0;
}