Reputation: 43547
So I have a FileReader
class, it looks like this:
#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; }
By itself it functions quite well.
When i create a FileReader
I must do so with a filename that specifies what file it has to open, and when I am finished with it, it automatically cleans up after itself.
But I find I'm having a bit of trouble putting this class to good use. You see, if I try to use it from another class, for instance an Image
class which represents a raster image, I'm not always creating an Image
by reading it from a file. So, I don't want to inherit FileReader
from Image
.
Neither can I make FileReader
a member of Image
, because I still need to initialize (and read out a file) when I initialize my Image
.
What I can do, however, is use FileReader
in passing in Image::loadFile()
, but then I must allocate a new buffer to store all the data, since FileReader
will be cleaned up at the end of the function call.
At first I thought that RAII was a great idea, but now, I'm not so sure. It's great for handling exceptions, but I want to prevent having to move my data around like this, while keeping a clean interface that will help prevent memory management nightmares. Is there a way to do that? Seems to me like I have to significantly restructure things in order to avoid juggling all the data across a series of dynamically allocated buffers. Should I use smart pointers?
Upvotes: 1
Views: 319
Reputation: 1314
You could possibly make FileReader *
a private member and overload your constructor.
public:
Image();
Image(const char* fileName);
So, the consumer for your Image class decides what happens. In the second constructor you initialize your FileReader *
and then destroy it in the destructor only if was initialized. I guess this might be RAII in the sense that the constructor on your object initializes which resource the object needs.
Hope this helps.
Upvotes: 0
Reputation: 6601
RAII IS a good idea. You need to split up your file and your "open file" objects. Make a new class called OpenFile, with a constructor like the following OpenFile(FileReader &f); Your resource is an open file, not the filename.
Upvotes: 2