我的代码中存在样式问题,我想知道其他人是否遇到过。 假设我有一个类没有默认构造函数,或者有一个我不想调用的默认构造函数(出于性能和样式的原因)。例如,假设这是一个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异常......有更好的方法吗?
答案 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();