提问者:小点点

有没有更好的方法来实现try.。catch机制?


LinkedList.h

#pragma once

class LinkedList {
    int size = 1;
    struct Node {
        int ivar = 0;
        Node* next = nullptr;
    };
    Node* rootNode = new Node();
    Node* createNode(int ivar);
    auto getSize() const { return size; }
public:
    LinkedList() = delete;
    LinkedList(int val) {
        rootNode->ivar = val;
    }
    const bool addNode(int val, int pos);
    const bool delNode(int pos);
    ~LinkedList() = default;
};


LinkedList.cpp

#include <exception>
#include "LinkedList.h"

LinkedList::Node* LinkedList::createNode(int ivar) {
    try {
        Node* newNode = new Node();
        newNode->ivar = ivar;
        return newNode;
    }
    catch (const std::exception&) {
        return nullptr;
    }
}

const bool LinkedList::addNode(int val, int pos = -1) {
    pos = (pos >= size) || (pos < 0) ? getSize() - 1 : pos;
    Node* newNode = createNode(val);
    if (newNode == nullptr) {
        return false;
    }
    Node* temp_ptr = rootNode;
    for (int i = 0; i < pos; i++) {
        temp_ptr = temp_ptr->next;
    }
    temp_ptr->next = newNode;
    size++;
    return true;
}

const bool LinkedList::delNode(int pos) {
    pos = (pos >= size) || (pos < 0) ? getSize() - 1 : pos;
    try {
        auto temp_ptr = rootNode;
        if (pos == 0) {
            rootNode = rootNode->next;
        }
        else {
            for (int i = 0; i < pos - 1; i++) {
                temp_ptr = temp_ptr->next;
            }
        }
        temp_ptr->next = temp_ptr->next->next;
    }
    catch (const std::exception&) {
        return false;
    }
    size--;
    return true;
}

这是链表赋值的代码。 有没有更好的办法来实施试抓机制?


共2个答案

匿名用户

如果您捕获到一个异常,尤其是像std::exception这样的常规异常,它通常是所有其他异常的基类,您通常希望记录它并重新抛出它。 沉默一些一般的异常是一个可怕的想法,它挫败了异常的目的。 一般来说:

  • 如果存在您确切知道如何恢复的特定异常(如GUI失败,返回文本用户接口),请执行备份计划。
  • 在所有其他情况下,将其记录(记录到日志文件,日志流等)重新引发异常。

在您的特定情况下,最好不要捕捉异常,因为您没有对它做任何特别的事情。

您还可以看到这篇标题为“声明性控制流”的演讲,它描述了替换try...catch以改进代码结构的方法。

匿名用户

异常不是实现if/else的替代方法。 异常具有完全不同的,复杂得多的语义,它们仅仅是为了处理错误而产生的。 事实上,正是这样一个主题,直到1994年才真正有人知道如何编写适当的异常安全代码。

  • 打印/记录它们等等
  • 重新抛出它们,以便调用您的方法的任何人都可以捕获异常并知道哪里出了问题。
    调用
  • std::terminater,程序退出
  • 当无法在函数内部本地处理错误时,使用异常。 示例:

当您知道某个函数或某个代码段可能引发异常时,请使用try/catch

try{//此处的代码可以抛出this_func_can_throw_in_some_cases();}catch(exception&e){。。。}

struct A{
   A() {
    //some error happened here. Now you can't tell anyone about the error.
    //You can't return error code or true/false from the constructor.
    //Use exceptions!
    throw myexception("Something bad happened");
   }
};

//
void somefunc()
{
    try {
       A a; //constructor of A can throw
    } catch (const myexception& e) {
        std::cout << e.what() << std::endl;  //
        throw; //rethrow the exception.
    }
}

CreateNode方法中的代码中:

LinkedList::Node* LinkedList::createNode(int ivar) {
    try {
        Node* newNode = new Node();
        newNode->ivar = ivar;
        return newNode;
    }
    catch (const std::bad_alloc &ba) {
        std::cout << "Failed to allocate: " << ba.what() << std::endl;
        throw;
    }
}

int main()
{
  try {
     list.createNode(...)
  } catch (const std::bad_alloc& ba)
  {
     //failed...
     //no rethrowing, we are already in main and we can't rethrow stuff from here.
  }
}

这是毫无意义的:

    try {
        auto temp_ptr = rootNode;
        if (pos == 0) {
            rootNode = rootNode->next;
        }
        else {
            for (int i = 0; i < pos - 1; i++) {
                temp_ptr = temp_ptr->next;
            }
        }
        temp_ptr->next = temp_ptr->next->next;
    }
    catch (const std::exception&) {
        return false;
    }

这里不需要try/catch,因为try块中的任何内容都不能抛出。 如果什么都不能,那么就只是坐在那里无所事事。 你可以安全地移除它。

我建议您阅读isocpp常见问题解答中的异常和错误处理章节,以获得有关该主题的详细介绍。 特别了解

  • 了解异常安全保证(弱/强)
  • 不使用异常的位置(例如,在析构函数中)