2011-09-19 52 views
1

所以我有一个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。所以,我不想从Image继承FileReader

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

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

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

+3

为什么不根据你拥有的对象和他们的行为建立你的对象模型,而不是基于你已经实现的一个类,并且即使它不适合你的需要也不想重建? – littleadv

+2

你确定你已经理解了RAII的目的吗? –

+1

如果你要在不同的类之间移动指针,它最好使用智能指针而不是原始指针。这样你就不用担心释放这些指针所获取的资源,智能指针会为你处理这些。 –

回答

0

您可能会让FileReader *成为私人成员并重载您的构造函数。

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

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

希望这会有所帮助。

+0

我认为成员对象不能保持未初始化。 –

+0

对不起,我忘了把我的C++帽子放在...我正在考虑FileReader指针...编辑我的帖子... – Nabheet

+0

哦,好吧,我现在看到它。这实际上是一个非常聪明的方式。 –

2

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

+0

能否详细介绍一下? –