我有A类,它有构造函数A(字符串文件路径)
class A {
public:
A(string filePath);
private:
A();
}
我需要初始化A,稍后再使用它。构造函数A抛出异常。
int main() {
A a;
try {
a = A("./my/file/path");
} catch (exception e) {
return 1;
}
// Use a
return 0;
}
最优雅的解决方案是什么? (我不想拥有类似init函数的东西,因为它可以使空A对象成为可能。)
答案 0 :(得分:4)
最优雅的解决方案可能是将所有使用a
的逻辑移动到函数
int use_a(A &a);
int main() {
try {
A a("./my/file/path");
// if we reach here, no exception was thrown
// hence a is safe to use
return use_a(a);
} catch (exception e) {
// if we reach here a never really existed
return 1;
}
}
您更愿意避免两阶段初始化 - 这种方式use_a
可以隐含地依赖a
安全使用。
答案 1 :(得分:2)
最优雅的解决方案是:
int main() {
try {
A a("...");
// use a
} catch (const std::exception& e) {
// log e
return 1;
}
return 0;
}
答案 2 :(得分:1)
如果您不想要空A对象,请考虑删除默认构造函数。请注意,这使得使用某些stl容器更加困难,同时确保不存在无效对象。
除此之外,我认为使用throw in constructors非常允许。如果您不想这样做,请考虑noexcept关键字。请注意,析构函数中的抛出可能会导致问题并且通常会被避免。
答案 3 :(得分:1)
作为替代方案,您可以在"可选/可检查"中转换例外。使用std::optional
或std::unique_ptr
构建
std::optional<A> MakeA(const std::filesystem::path& path)
{
try {
return A{path};
} catch (std::exception& e) {
return std::nullopt;
}
}
int main() {
auto a = MakeA("./my/file/path");
if (!a) {
return 1;
}
// Use *a
return 0;
}