c++—断言、异常

一、 断言,主要用于在函数入口处进行参数检查,是否符合参数设置要求;

     (1)true:继续执行;false:终止运行;

     (2)特点:在程序运行时才能起作用,进行判断;

     (3)头文件:<cassert>

     (4)断言的代码一般放在函数或者成员函数的第一行,表达式多为函数的形参;

     (5)静态断言static_assert可以自定义违反断言时的错误提示信息,提示信息一般是一段字符串;一般很少用,因为其要求判断的表达式必须是常量,一般用配合constexpr修饰的变量(在编译器优化为常量);

#include <iostream>
#include <cassert>

using namespace std;

void func(int * ptr1, int * ptr2)
{
    assert(ptr1 && ptr2);
    cout<<(*ptr1)<<" : "<<(*ptr2)<<endl;
}

int main(int argc, char **argv)
{
    int a = 5;
    int b = 6;

    func(&a, &b);
    func(&a, nullptr);

    return 0;
}

二、 异常

    (1)异常与断言不同,异常不会立即终止程序运行;是一种面向对象语言处理错误的一种方式;

    (2)当一个函数出现自己无法处理的错误时,可以抛出异常,然后利用异常捕捉去处理;

    (3)语法,三个关键字;

        ①try:用于包含可能会出现异常的代码块或者函数,后面通常跟一个或者多个catch块;

        ②catch:用于捕捉异常;形式多样;其中catch(...)可以捕捉任意类型的异常;可以多个catch排序,异常信息会从上到下找到适配参数的catch块执行;

        ③throw:当问题出现时,throw可以抛出一个异常;

#include <iostream>
#include <cassert>
#include <string>

using namespace std;

void func(char * str1, char *str2)
{
    assert(str1 != nullptr);
    if(str2 == nullptr)
    {
        throw ("str2 is nullptr");
    }
    cout<<"ok"<<endl;
}

void pfunc(char * str1, char *str2)
{
    assert(str1 != nullptr);
    if(str2 == nullptr)
    {
        throw (777);
    }
    cout<<"ok"<<endl;
}

int main(int argc, char **argv)
{
    char name[10];
    try
    {
        func(name,nullptr);
        pfunc(name,nullptr);
    }
    catch(const char * errmsg)
    {
        cout<<errmsg<<endl;
    }
    try    //这里加一个try主要是因为当上面try内的两个函数均出现异常时,第二个异常无法显示;
    {
        pfunc(name,nullptr);
    }
    catch(int error)
    {
        cout<<"error num : "<<error<<endl;
    }

    return 0;
}

    (4)一些函数是不允许出现异常的,比如构造函数(若有异常,可能会导致对象不完整或者没有完全初始化)、析构函数(若有异常可能导致内存泄漏);

    (5)关键字noexcept

        ①主要用在一个操作或者函数不可能抛出任何异常,放在这个函数的后面;这样会给编译器更大的优化空间;

        ②使用noexcept的时机:构造函数、析构函数;

    (6)自定义异常体系,通过建立一个异常基类,派生类继承这个类,从而来定义出不同的异常;

#include <iostream>
#include <string>

using namespace std;

//基类 异常
class Exception
{
public:
    Exception(const char* str = nullptr, int id = 0) : _errmsg(str), _id(id)
    {

    }
    virtual void what()const = 0;  //纯虚函数,多态机制

protected:
   string _errmsg;//错误信息
   int _id;//错误码
};

//派生类
//数据库异常
class SqlException : public Exception
{
public:
    SqlException(const char *str = nullptr, int id = 1) : Exception(str, id)
    {

    }
    virtual void what()const
    {
        cout << "error msg:" << _errmsg << endl;
        cout << "error id:" << _id << endl;
    }
};

//网络异常
class HttpException :public Exception
{
public:
    HttpException(const char *str = nullptr, int id = 2) : Exception(str, id)
    {

    }
    virtual void what()const{
     cout << "error msg:" << _errmsg << endl;
     cout << "error id:" << _id << endl;
    }
};

//缓存异常
class CacheException :public Exception
{
public:
    CacheException(const char *str = nullptr, int id = 3) : Exception(str, id)
    {

    }
 
    virtual void what()const
    {
        cout << "error msg:" << _errmsg << endl;
        cout<< "error id:" << _id << endl;
    }
};
 
void test()
{
    //当网络连接失败,抛出这个异常即可
    //throw HttpException("Http fail", 2);
    //当缓存错误
    //throw CacheException("Cache error", 3);
    //当数据库错误
    throw SqlException("Sql error", 4);    //在抛出了一个派生类对象前,先初始化了一个类;
}

int main()
{
    try
    {
        test();
    }

    //用基类捕捉即可
    catch (const Exception& a)  //捕捉基类即可,会利用多态调用派生类的成员函数;
    {
        a.what();  //捕捉到异常后,调用该派生类对象的成员函数,将错误信息和错误代码打印;
    }

    catch (...)
    {
        cout << "unknow exception" << endl;
    }

    system("pause");

    return 0;
}

    (7)异常的优缺点

        优点:①更好的返回和描述错误信息,便于定位;②对于某些错误,不需要终止程序;

        缺点:①降低了代码可续性;②c++标准库的自定义体系不够细致,太笼统,需要我们自己定义各自的体系,造成混乱;

猜你喜欢

转载自blog.csdn.net/m0_72814368/article/details/130905912
今日推荐