【发布时间】:2009-12-18 15:17:18
【问题描述】:
我有类似的东西:
#include "MyImage.hpp" // MyImage wraps the Qt library image class
namespace fs = boost::filesystem;
class ImageCollection {
public:
ImageCollection(const char* path);
private:
const fs::path path_;
deque<MyImage> instanceDeque_;
}
ImageCollection(const char* path) :
path_(fs::is_directory(path) ?
fs::complete(path) :
fs::complete(path).parent_path()) /* Can I even do this? */
{
/*** code in question ***/
fs::directory_iterator endIter;
for(fs::directory_iterator dirIter(path_); dirIter != endIter; dirIter++) {
instanceDeque_.push_back(MyImage(*dirIter));
}
}
当 *dirIter 是非图像文件的 fs::path 时,MyImage 构造函数会抛出 MyInvalidFileException。
我希望 MyImage 和 ImageCollection 是不可变的。
我可以:
try {
instanceDeque_.push_back(MyImage(*dirIter));
}
catch(const MyInvalidFileException& e) { // oops, tnx Nemanja T.
// remember *dirIter in a list of non-Image files, to use later
continue;
}
当它抛出时会发生什么?双端队列中是否有僵尸 MyImage 或僵尸元素?或者这实际上是正确的方法吗? (即 push_back() 被中止并且没有创建 MyImage。)
我目前有一个混乱的解决方法:
// load up an empty MyImage, which I'd rather not do
instanceDeque_.push_back(MyImage());
for(fs::directory_iterator dirIter(path_); dirIter != endIter; dirIter++) {
MyImage& attemptImage = instanceDeque_.back();
bool success = attemptImage.loadPath(*dirIter); // "fill" the empty MyImage
if (success)
instanceDeque_.push_back(MyImage()); // prepare another empty MyImage
}
instanceDeque_.pop_back(); // discard the empty MyImage
其中 MyImage 使用 null QImage* 初始化,并且 loadPath() 在堆上创建 QImage。这迫使我到处进行空指针检查。我认为如果文件可以打开,应该有一个方法来拥有一个 QImage 的实例,如果文件不能打开,构造就会失败。
【问题讨论】:
-
按常量引用而不是按值捕获。
-
当 QDir 和朋友都在的时候,你为什么要使用 Boost 来管理路径?此外,deque 有点没用,因为 QList 在很多情况下都表现得非常好,并且提供了一个更干净、更易于使用的 API。
-
QList接口如何更好?在我看来完全一样。
-
为什么图像构造函数必须抛出异常?它可以像 QImage 一样简单地创建一个“空”图像。
-
出于(我猜的)典型原因,我想尽可能使用 STL,然后是 Boost,然后是 Qt。此外,通过这样做,我学到了很多关于处理 C++ 编程的外部库的知识。 @rpg - “null”是我已经在做的,但它不仅需要我处理 null 情况,我根本不需要 null 图像。我以后不会更改图像。我想这样设计,如果 QImage 无法打开图像,那么从一开始就永远不要构造并且永远不要插入到容器中。
标签: c++ exception constructor