1.类型强制转换
- static_cast,interpret_cast,const_cast和dynamic_cast
- 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 的值变为 3
n = static_cast<int>(a); //调用a.operator int, n的值变为 1
p = static_cast<char*>(a);
//调用a.operator int *,p的值变为 NULL
n = static_cast<int> (p);
//编译错误, static_cast不能将指针转换成整型
p = static_cast<char*>(n);
//编译错误, static_cast不能将整型转换成指针
return 0;
}
- 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 引用 a
r = 200; //把 a.i 变成了 200
cout << a.i << "," << a.j << endl; // 输出 200,100
int n = 300;
A * pa = reinterpret_cast<A*> (&n); //强行让 pa 指向 n
pa->i = 400; // n 变成 400
pa->j = 500; //此条语句不安全,很可能导致程序崩溃
cout << n << endl; // 输出 400
long long la = 0x12345678abcdLL;
pa = reinterpret_cast<A*>(la);
// la太长,只取低32位0x5678abcd拷贝给pa
unsigned int u = reinterpret_cast<unsigned int>(pa);
//pa逐个比特拷贝到u
cout << hex << u << endl; //输出 5678abcd
typedef void(*PF1) (int);
typedef int(*PF2) (int, char *);
PF1 pf1; PF2 pf2;
pf2 = reinterpret_cast<PF2>(pf1);
//两个不同类型的函数指针之间可以互相转换
}
- const_cast
用来去除const属性的转换。将const引用转换成同类型的非const引用,将const指针转换为同类型的非const指针时用它。
const string s = “Inception”;
string & p = const_cast<string&>(s);
string * ps = const_cast<string*>(&s);
// &s的类型是const string *
- 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 reinterpret_cast" << endl; //不会执行
pd = dynamic_cast<Derived*> (&b);
if (pd == NULL)
//结果会是NULL,因为 &b不是指向派生类对象,此转换不安全
cout << "unsafe dynamic_cast1" << endl; //会执行
pd = dynamic_cast<Derived*> (&d); //安全的转换
if (pd == NULL) //此处pd 不会为NULL
cout << "unsafe dynamic_cast2" << endl; //不会执行
return 0;
}
2.异常处理
- 程序运行中难免发生错误
数组元素的下标超界、访问NULL指针
除数为0
动态内存分配new需要的存储空间太大 - 引起原因
代码质量低
输入数据不符合要求
程序的算法设计时考虑不周到 - 用try、catch进行异常处理
#include <iostream>
using namespace std;
int main()
{
double m, n;
cin >> m >> n;
try {
cout << "before dividing." << endl;
if (n == 0)
throw - 1; //抛出int类型异常
else
cout << m / n << endl;
cout << "after dividing." << endl;
}
catch (double d) {
cout << "catch(double) " << d << endl;
}
catch (int e) {
cout << "catch(int) " << e << endl;
}
cout << "finished" << endl;
return 0;
}
/*
程序运行结果如下:
9 6↙
before dividing.
1.5
after dividing.
finished
*/
- 捕获任何异常的catch块
#include <iostream>
using namespace std;
int main()
{
double m, n;
cin >> m >> n;
try {
cout << "before dividing." << endl;
if (n == 0)
throw - 1; //抛出整型异常
else if (m == 0)
throw - 1.0; //抛出double型异常
else
cout << m / n << endl;
cout << "after dividing." << endl;
}
catch (double d) {
cout << "catch(double) " << d << endl;
}
catch (...) {
cout << "catch(...) " << endl;
}
cout << "finished" << endl;
return 0;
}
/*
程序运行结果:
9 0↙ 0 6↙
before dividing. before dividing.
catch(...) catch(double) -1
finished finished
注意: try块中定义的局部对象,发生异常时会析构!
*/
- 异常的再抛出
如果一个函数在执行的过程中,抛出的异常在本函数内就被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("devided 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 << e.msg << endl;
}
cout << "f=" << f << endl;
cout << "finished" << endl;
return 0;
}
/*
输出结果:
salary < 0
tax counted
devided by zero
f=1.2
finished
*/
3.运行时类型检查
C++运算符typeid是单目运算符,可以在程序运行过程中获取一个表达式的值的类型。 typeid运算的返回值是一type_info类的对象,里面包含了类型的信息。
#include <iostream>
#include <typeinfo> //要使用typeinfo,需要此头文件
using namespace std;
struct Base { }; //非多态基类
struct Derived : Base { };
struct Poly_Base { virtual void Func() { } }; //多态基类
struct Poly_Derived : Poly_Base { };
int main()
{
//基本类型
long i; int * p = NULL;
cout << "1) int is: " << typeid(int).name() << endl;
//输出 1) int is: int
cout << "2) i is: " << typeid(i).name() << endl;
//输出 2) i is: long
cout << "3) p is: " << typeid(p).name() << endl;
//输出 3) p is: int *
cout << "4) *p is: " << typeid(*p).name() << endl;
//输出 4) *p is: int
//非多态类型
Derived derived;
Base* pbase = &derived;
cout << "5) derived is: " << typeid(derived).name() << endl;
//输出 5) derived is: struct Derived
cout << "6) *pbase is: " << typeid(*pbase).name() << endl;
//输出 6) *pbase is: struct Base
cout << "7) " << (typeid(derived) == typeid(*pbase)) << endl;
//输出 7) 0
//多态类型
Poly_Derived polyderived;
Poly_Base* ppolybase = &polyderived;
cout << "8) polyderived is: " << typeid(polyderived).name() << endl;
//输出 8) polyderived is: struct Poly_Derived
cout << "9) *ppolybase is: " << typeid(*ppolybase).name() << endl;
//输出 9) *ppolybase is: struct Poly_Derived
cout << "10) " << (typeid(polyderived) != typeid(*ppolybase)) << endl;
//输出 10) 0
}