在变量声明上捕获异常

时间:2012-06-23 23:12:45

标签: c++ exception exception-handling

我的代码中存在样式问题,我想知道其他人是否遇到过。 假设我有一个类没有默认构造函数,或者有一个我不想调用的默认构造函数(出于性能和样式的原因)。例如,假设这是一个File对象。

现在假设我有一个文件包含要删除的文件名列表...我想要执行以下操作:

File f("foo");
for (const string& filenameToDelete : f.Lines())
    File(filenameToDelete).Delete();

File可以在构造函数或Delete函数中抛出FileNotFound。我的代码必须首先丢失删除文件,但如果文件“foo”不存在则不得抛出(缺少文件只意味着没有要删除的内容)。

我希望我能写出这样的东西:

try { File f("foo"); } catch (FileNotFound) { return; }
for (const string& filenameToDelete : f.Lines())
    File(filenameToDelete).Delete();

但显然无法编译。 我能做到这一点:

unique_ptr<File> f;
try { f.reset(new File("foo")); } catch (FileNotFound) { return; }
for (const string& filenameToDelete : f->Lines())
    File(filenameToDelete).Delete();

但我有点不喜欢这样一个事实:我需要为一个变量进行内存分配,否则可能会被堆栈分配...

如果我想用一些我没有做堆分配的任意约束来编写代码,我只能想到这样做:

struct FileNotFoundToRethrow : public FileNotFound {};
try
{
    File f("foo");
    try
    {
        for (const string& filenameToDelete : f.Lines())
            File(filenameToDelete).Delete();
    }
    catch (FileNotFound)
    {
        throw FileNotFoundToRethrow();
    }
}
catch (FileNotFoundToRethrow) { throw; }
catch (FileNotFound) { return; }

我发现这很难看,很难看到我想做的就是处理第一行抛出的FileNotFound异常......有更好的方法吗?

2 个答案:

答案 0 :(得分:1)

我会用旗帜

来做
bool throwOnNotFound = false;

try
{
    File f("foo");

    throwOnNotFound = true;

    for (const string& filenameToDelete : f.Lines())
        File(filenameToDelete).Delete();
}
catch (FileNotFound)
{
    if (throwOnNotFound)
        throw;
}

答案 1 :(得分:1)

对于所有感到特别聪明的人,可能有一种方法,extending the lifetime with reference to const。但也有缺点。类必须具有null(或默认)对象,并且引用是 const

File fooFile()
{
    try { return File("foo"); } catch (FileNotFound) { return File::Default; }
}

使用它:

const File& foo = fooFile();

if (foo.IsDefault())
    return;

for (const string& filenameToDelete : f.Lines())
        File(filenameToDelete).Delete();