C++学习 day12

发布于 17 天前  85 次阅读


Day 12:自定义异常与函数模板

本节代码位置:

2-代码/day12-自定义异常/69-自定义异常类型示例.cpp
2-代码/day12-自定义异常/70-函数模板示例.cpp
2-代码/day12-自定义异常/70-函数模板练习.cpp

1、自定义异常

C++ 标准库提供了 std::exception 作为常用异常基类。需要表达自己的错误类型时,可以公开继承它,并重写 what()

class MyException : public std::exception
{
public:
    MyException(const char *errmsg) : errmsg(errmsg) {}

    const char *what() const noexcept override
    {
        return errmsg;
    }

private:
    const char *errmsg;
};

这里的 errmsg 保存错误描述;what() 是给调用者读取错误信息的统一接口。

2、抛出和捕获异常

发现错误时使用 throw 抛出异常对象:

void foo()
{
    throw MyException("this is a test!");
}

调用处用 try 包住可能出错的代码,再用 catch 处理:

try
{
    foo();
}
catch (const std::exception &err)
{
    cout << "err: " << err.what() << endl;
}

虽然抛出的是 MyException,但它继承自 std::exception,所以可以用基类引用捕获。这样既能处理多种标准异常,又能保留派生类的真实异常信息。

3、异常使用要点

1. throw 用于抛出异常对象。
2. try 中放可能发生异常的代码。
3. catch 负责匹配并处理异常。
4. 异常对象通常按值抛出,按 const 引用捕获。
5. 按引用捕获能避免不必要的拷贝,也能避免对象切片。
6. what() 返回 const char*;noexcept 表示该函数不会再抛出异常。

异常适合处理“当前函数无法在原地恢复”的错误。函数发现问题后把异常交给上层,上层决定记录、提示、重试还是退出。


4、函数模板

函数模板把算法逻辑写一次,再由编译器根据实参类型生成对应的函数。

template <typename T>
void Swap(T &a, T &b)
{
    T temp = a;
    a = b;
    b = temp;
}

调用时会自动推导模板参数:

int x = 1;
int y = 2;
Swap(x, y); // T 推导为 int

double a = 1.1;
double b = 2.2;
Swap(a, b); // T 推导为 double

同一个 Swap 可以用于多种类型,因此不必分别写 SwapIntSwapDouble

5、多个模板参数与显式指定

template <typename T1, typename T2>
T1 sum(T1 a, T2 b)
{
    return a + b;
}

cout << sum<double, double>(1, 2.2) << endl;

sum 有两个类型参数。大多数情况下编译器可以推导;当想控制返回类型或推导不符合预期时,也可以像示例一样显式写出模板实参。

6、数组长度作为模板参数

template <typename T, size_t N>
int findValue(const T (&arr)[N], const T &value)
{
    for (size_t i = 0; i < N; ++i)
    {
        if (arr[i] == value)
            return static_cast<int>(i);
    }
    return -1;
}

T 表示元素类型,N 表示数组长度。参数 const T (&arr)[N] 是“数组的引用”,调用时编译器会自动得到长度,不需要再额外传数组大小。

7、Day12 总结

1. 自定义异常可继承 std::exception,并重写 what()。
2. 用 throw 抛异常,用 try/catch 处理异常。
3. 捕获异常优先使用 const 基类引用。
4. 函数模板让一套算法支持多种数据类型。
5. 模板参数既可以是类型,也可以是编译期常量,例如数组长度 N。

一句话记忆:异常负责把错误交给调用方处理;函数模板负责把重复算法写成可复用的通用函数。


"When faced with uncertainty, ask the spring breeze."