版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/abc15766228491/article/details/83019526
强制类型转换 :static_cast、interpret_cast、const_cast、dynamic_cast
1、static_cast:static_cast 用来进行比较“自然”和低风险的转换,比如整型和实数型、字符型之间的互相转换。static_cast不能用来在不同类型的指针之间互相转换,也不能用于不同类型的引用之间的转换,也不能用于不同类型的引用之间的转换。
#include <iostream>
using namespace std;
class A{
public:
operator int(){return 1;}
operator char*(){return NULL;}
};
int main()
{
A a;
int n;
char *p="New Dragon Inn";
n = static_cast<int>(3.14);
n = static_cast<int>(a);
p = static_cast<char *>(a);
// n = static_cast<int>(p);//编译错误,static_cast不能将指针转换成整型
// p = static_cast<char*>(n);//编译错误,static_cast不能将整型转换成指针
return 0;
}
2、reinterpret_cast:reinterpret_cast用来进行各种不同类型的指针之间的转换、不同类型之间转换、以及指针和能容纳得下指针的整数类型之间的转换。转换的执行的是逐个比特拷贝的操作
#include <iostream>
using namespace std;
class A{
public:
int i;
int j;
A(int n):i(n),j(n){}
};
int main()
{
A a(100);
int& r = reinterpret_cast<int&>(a);
r=200;//将a.i改变成了200
cout<<a.i<<","<<a.j<<endl;
int n=300;
A*pa=reinterpret_cast<A*>(&n);
pa->i=400;
pa->j=500;
cout<<n<<endl;
long long la=0x12345678abcdLL;
pa = reinterpret_cast<A*>(la);//la 太长,只取低32位5678abcd拷贝给pa
//下面两句在课程中是貌似是可以的,不过,在我电脑上有问题。。
// unsigned int u = reinterpret_cast<unsigned int>(pa);
// cout<<hex<<u<<endl;
typedef void(*PF1)(int);
typedef int(*PF2)(int, char *);
PF1 pf1;
PF2 pf2;
pf2 = reinterpret_cast<PF2>(pf1);
}
//输出:
/*
200,100
400
*/
3、const_cast:用来进行去除const属性的转换。将const引用转换成同类型的非const引用。将const指针转换为同类型的非const指针时用题它,如:
const string s="Inception";
string &p=const_cast<string &>(s);
string *ps = const_cast<string *>(&s);
4、dynamic_cast
dynamic_cast专门用于将多态基类指针或引用,强制转换成派生类的指针或引用,而且能够检测转换的安全性。对于不安全的指针转换,转换结果返回NULL指针。dynamic_cast不能用于将非多态基类的指针或引用,强制转换为派生类的指针或引用。(多态基类:包含虚函数的基类)
#include <iostream>
#include <string>
using namespace std;
// 多态基类
class Base{
public:
virtual ~Base(){}
};
class Derived:public Base{};
int main()
{
Base b;
Derived d;
Derived *pd;
pd = reinterpret_cast<Derived*>(&b);
if(pd==NULL)
{
//此处pd不会为NULL
// reinterpret_cast不检测安全性,总是进行转换
cout<<"unsafe"<<endl;
//不会执行
}
pd = dynamic_cast<Derived*>(&b);
if(pd==NULL)
{
//结果会是NULL因为&b不是指向派生类对象,此处转换不安全
cout<<"unsafe dynamic_cast 1"<<endl;
}
Base *pb=&d;
pd = dynamic_cast<Derived*>(pb);
if(pd==NULL)
{
cout<<"unsafe dynamic_cast 2"<<endl;
}
return 0;
}
/*
* 输出:
unsafe dynamic_cast 1
*/
dynamic_cast:实现基类引用到派生类引用之间的转换
Derived & r=dynamic_cast<Derived &>(b);
如何判断改转换是否安全呢?答案:不安全则抛出异常
异常处理
#include <iostream>
using namespace std;
int main()
{
double m, n;
cin>>m>>n;
try{
// try 块
cout<<"before dividing."<<endl;
// 一旦到throw那try就停止运行,进catch块
//
if(n==0)
throw -1;//抛出int类型异常,
else if(m==0)
throw -1.0;
else
cout<<m/n<<endl;
cout<<"after dividing"<<endl;
}
//catch从上到下检测
catch(double d) {
//捕获double型异常
cout<<"catch(double)"<<d<<endl;
}
catch(int e){
//捕获整型异常
cout<<"catch(int)"<<e<<endl;
}
catch(...){
//捕获任何类型的异常
cout<<"catch(...)"<<endl;
}
cout<<"finished"<<endl;
return 0;
}
0 6
before dividing.
catch(double)-1
finished
异常的再抛出
如果一个函数在执行的过程中,抛出的异常在本函数内就被catch块捕获并处理了,那么该异常就不会抛给这个函数的调用者(也称“上一层的函数”);如果异常在本函数中没被处理,就会被抛给上一层的函数
#include <iostream>
#include <string>
using namespace std;
class CException {
public:
string msg;
CException(string s) : msg(s) {}
};
double Devide(double x, double y) {
if (y == 0)
throw CException("devide by zero");
cout << "in Devide" << endl;
return x / y;
}
int CountTax(int salary){
try{
if(salary<0)
throw -1;
cout<<"counting tax"<<endl;
}
catch(int)
{
cout<<"salary<0"<<endl;
}
cout<<"tax counted"<<endl;
return salary*0.15;
}
int main()
{
double f=1.2;
try {
//下面这个异常被处理了
CountTax(-1);
//下面这个异常被捕获
f=Devide(3,0);
cout<<"end of try block"<<endl;
}
catch(CException e) {
cout<<"in main catch "<<e.msg<<endl;
}
cout<<"f="<<f<<endl;
cout<<"finished"<<endl;
return 0;
}
salary<0
tax counted
in main catch devide by zero
f=1.2
finished
c++标准异常类:c++标准库中有一些类代表异常,这些类都是从exception类派生而来。常用的几个异常类如下:
bad_cast:在用dynamic_cast进行从多态基类对象(或引用),到派生类的引用的强制类型转换时,如果转换是不安全的,则会抛出此异常。
#include <iostream>
#include <stdexcept>
#include <typeinfo>
using namespace std;
class Base{
virtual void func(){}
};
class Derived:public Base{
public:
void Print(){}
};
void PrintObj(Base& b)
{
try{
//基类引用强制转为派生类引用
Derived& rd = dynamic_cast<Derived&>(b);
// 此转换若不安全,会抛出bad_cast异常
rd.Print();
}
catch(bad_cast& e){
cerr<<e.what()<<endl;
}
}
int main()
{
Base b;
PrintObj(b);
return 0;
}
// 输出:std::bad_cast
bad_alloc:在用new运算符进行动态内存分配时,如果没有足够的内存则会引发此异常。
#include <iostream>
#include <stdexcept>
using namespace std;
int main()
{
try{
char *p = new char[0x7ffffffff];
//无法分配这些空间,会抛异常
}
catch(bad_alloc& e)
{
cerr<<e.what()<<endl;
}
return 0;
}
// 输出:std::bad_alloc
out_of_range 用vector或string的at成员函数根据下标访问元素时,如果下标越界,就会抛出此异常。例如:
#include <iostream>
#include <stdexcept>
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<int> v(10);
try{
// 如果[]不检测下标越界,at()会检测,所以速度慢
v.at(100)=100;
// 抛出out_of_range的异常
}
catch(out_of_range& e){
cerr<<e.what()<<endl;
}
string s="hello";
try{
char c=s.at(100);
//抛出out_of_range的异常
}
catch(out_of_range& e){
cerr<<e.what()<<endl;
}
return 0;
}
//输出:
// vector::_M_range_check: __n (which is 100) >= this->size() (which is 10)
// basic_string::at: __n (which is 100) >= this->size() (which is 5)