美文网首页
C++11新特性(3)

C++11新特性(3)

作者: su945 | 来源:发表于2020-08-04 21:39 被阅读0次

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
}

相关文章

网友评论

      本文标题:C++11新特性(3)

      本文链接:https://www.haomeiwen.com/subject/mbqirktx.html