gpt4 book ai didi

C++,处理来自构造函数的异常

转载 作者:行者123 更新时间:2023-12-02 09:48:04 24 4
gpt4 key购买 nike

我有一个从外部文件加载的类,所以理想情况下,如果加载失败,我希望它的构造函数从给定的路径加载,如果文件未找到/不可读,我想抛出一个错误(抛出错误来自构造函数并不是一个可怕的想法,见 ISO's FAQ )。
但是这有一个问题,我想以某种受控的方式自己处理错误,我想立即这样做,所以我需要在这个对象的构造函数周围放置一个 try-catch 语句……如果我这样做了也就是说,该对象未在 try 语句之外声明,即:

//in my_class.hpp
class my_class
{
...
public:
my_class(string path);//Throws file not found, or other error error
...
};


//anywhere my_class is needed
try
{
my_class my_object(string);
}
catch(/*Whatever error I am interesetd in*/)
{
//error handling
}
//Problem... now my_object doesn't exist anymore
我尝试了很多方法来解决它,但我真的不喜欢它们中的任何一个:
首先,我可以使用指向 my_class 的指针而不是类本身:
my_class* my_pointer;
try
{
my_class my_pointer = new my_class(string);
}
catch(/*Whatever error I am interesetd in*/)
{
//error handling
}
问题是这个对象的实例并不总是在创建它的同一个对象中结束,所以正确删除所有指针很容易出错,此外,我个人认为让一些对象成为指针是很丑陋的对象,并让大多数其他对象成为“常规对象”。
其次,我可以以几乎相同的方式使用只有一个元素的 vector :
std::vector<my_class> single_vector;
try
{
single_vector.push_back(my_class(string));
single_vector.shrink_to_fit();
}
catch(/*Whatever error I am interesetd in*/)
{
//error handling
}
我不喜欢有很多单元素 vector 的想法。
第三,我可以创建一个空的仿构造函数并使用另一个加载函数,即
//in my_class.hpp
class my_class
{
...
public:
my_class() {}// Faux constructor which does nothing
void load(string path);//All the code in the constructor has been moved here
...
};


//anywhere my_class is needed
my_class my_object
try
{
my_object.load(path);
}
catch(/*Whatever error I am interesetd in*/)
{
//error handling
}
这有效,但在很大程度上违背了拥有构造函数的目的,所以我也不喜欢这个。
所以我的问题是,这些可能会在构造函数中抛出错误的构造对象的方法中,哪一种是最好的(或最不坏的)?有没有更好的方法来做到这一点?
编辑:为什么不直接在 try 语句中使用对象
因为该对象可能需要在程序第一次启动时创建,并在很晚之后停止。在最极端的情况下(在这种情况下我也确实需要)基本上是:
int main()
{
try
{
//... things which might fail

//A few hundred lines of code
}
catch(/*whaveter*/)
{
}
}
我认为这使我的代码难以阅读,因为 catch 语句与实际出错的地方相距甚远。

最佳答案

一种可能性是将构造和错误处理包装在一个函数中,返回构造的对象。例子 :

#include <string>

class my_class {
public:
my_class(std::string path);
};

my_class make_my_object(std::string path)
{
try {
return {std::move(path)};
}
catch(...) {
// Handle however you want
}
}

int main()
{
auto my_object = make_my_object("this path doesn't exist");
}
但是要注意这个例子是不完整的,因为当构建失败时你并不清楚你打算做什么。 catch块必须返回某些东西,抛出或终止。
  • 如果您可以返回一个不同的实例,一个具有“坏”或“默认”状态的实例,您可以在 my_class(std::string path) 中将您的实例初始化为该状态。当确定路径无效时。所以在这种情况下,try/catch块是不需要的。
  • 如果您重新抛出异常,那么一开始就没有必要捕获它。在这种情况下,try/catch块也不需要,除非你想做一些额外的工作,比如日志记录。
  • 如果你想终止,你可以让异常不被捕获。同样,在这种情况下,try/catch块是不需要的。

  • 这里真正的解决方案可能是不使用 try/ catch完全阻止,除非您确实可以执行错误处理,否则不应将其作为 my_class 的一部分来实现。这在问题中没有体现出来(也许是后备路径?)。

    关于C++,处理来自构造函数的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63413320/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com