面向对象的编程概念和资源管理

时间:2011-09-19 20:03:44

标签: c++

所以我有一个FileReader类,它看起来像这样:

#define DISALLOW_COPY(type) \
    type(const type&); \
    void operator=(const type&)

class FileReader { 
    FILE *file; 
    DISALLOW_COPY(FileReader);
protected:
    unsigned char *data; 
    long size;
public:
    FileReader(const char *filename);
    ~FileReader();
    unsigned long getSize();
    unsigned char *getFileData();
};


FileReader::FileReader(const char *filename) {

    file = NULL; data = NULL;
    if (!(file = fopen(filename, "rb"))) { throw std::runtime_error("File could not be opened."); }
    fseek(file,0,SEEK_END);
    size = ftell(file);
    rewind(file);
    data = new unsigned char [size];
    VERIFY(size == (long)fread(data, 1, size, file));
    fclose(file);
#ifdef DEBUG
    PRINT("FileReader opening file "); printf("%s, %ld bytes.\n",filename,size);
#endif
}
FileReader::~FileReader() {
    delete[] data;
}
unsigned char *FileReader::getFileData() { return data; }
unsigned long FileReader::getSize() { return size; }

它本身功能很好。

当我创建FileReader时,我必须使用一个文件名来指定它必须打开的文件,当我完成它时,它会自动清理。

但是我发现我在使用这门课时遇到了一些麻烦。你看,如果我试图从另一个类中使用它,例如一个表示光栅图像的Image类,我不是总是通过阅读它来创建一个Image从文件。所以,我不想从FileReader继承Image

我也不能让FileReader成为Image的成员,因为我在初始化Image时仍需要初始化(并读出文件)。

然而,我可以做的是使用FileReader传递Image::loadFile(),但是我必须分配一个新缓冲区来存储所有数据,因为FileReader将被清理在函数调用结束时。

起初我认为RAI​​I是一个好主意,但现在,我不太确定。它非常适合处理异常,但我想防止像这样移动我的数据,同时保持一个干净的界面,这将有助于防止内存管理的噩梦。有没有办法做到这一点?在我看来,我必须对事物进行重大调整,以避免在一系列动态分配的缓冲区中处理所有数据。我应该使用智能指针吗?

2 个答案:

答案 0 :(得分:2)

RAII IS 是个好主意。您需要拆分文件和“打开文件”对象。创建一个名为OpenFile的新类,使用如下OpenFile(FileReader& f)之类的构造函数;您的资源是一个打开的文件,而不是文件名。

答案 1 :(得分:0)

您可以使FileReader *成为私有成员并重载您的构造函数。

public:
    Image();
    Image(const char* fileName);

因此,Image类的使用者决定会发生什么。在第二个构造函数中,初始化FileReader *,然后仅在初始化时才在析构函数中销毁它。我想这可能是RAII,因为对象上的构造函数初始化了对象需要的资源。

希望这有帮助。