程序设计与算法(三)第十周 c++新特性和c++高级主题(3)

版权声明:本文为博主原创文章,未经博主允许不得转载。 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)

到此,所有课程终于结束,感谢老师的热情讲解,以后继续学习c++吧!

猜你喜欢

转载自blog.csdn.net/abc15766228491/article/details/83019526