强制类型转换 :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) ;
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 ;
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) ;
typedef void ( * PF1) ( int ) ;
typedef int ( * PF2) ( int , char * ) ;
PF1 pf1;
PF2 pf2;
pf2 = reinterpret_cast< PF2> ( pf1) ;
}
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 )
{
cout<< "unsafe" << endl;
}
pd = dynamic_cast< Derived* > ( & b) ;
if ( pd== NULL )
{
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 ;
}
dynamic_cast:实现基类引用到派生类引用之间的转换
Derived & r=dynamic_cast<Derived &>(b);
如何判断改转换是否安全呢?答案:不安全则抛出异常
异常处理
#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 ;
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;
}
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) ;
rd. Print ( ) ;
}
catch ( bad_cast& e) {
cerr<< e. what ( ) << endl;
}
}
int main ( )
{
Base b;
PrintObj ( b) ;
return 0 ;
}
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 ;
}
out_of_range 用vector或string的at成员函数根据下标访问元素时,如果下标越界,就会抛出此异常。例如:
#include <iostream>
#include <stdexcept>
#include <vector>
#include <string>
using namespace std;
int main ( )
{
vector< int > v ( 10 ) ;
try{
v. at ( 100 ) = 100 ;
}
catch ( out_of_range& e) {
cerr<< e. what ( ) << endl;
}
string s= "hello" ;
try{
char c= s. at ( 100 ) ;
}
catch ( out_of_range& e) {
cerr<< e. what ( ) << endl;
}
return 0 ;
}
到此,所有课程终于结束,感谢老师的热情讲解,以后继续学习c++吧!