Sign in to follow this  
monp

Using a Class within a Class.

Recommended Posts

I am having trouble getting this to work.
//a.h
class A
{
	public:
		FileManager *fmgr;
		A();
		~A();
		int x;
		int xx;
};

//a.cpp
#include "A.h"

A::A()
{
	this->fmgr = new FileManager;
}

~A::A()
{
	delete fmgr;
}


a.h(4) : error C2143: syntax error : missing ';' before '*' a.h(4) : error C4430: missing type specifier - int assumed. a.cpp(5) : error C2039: 'fmgr' : is not a member of 'A' a.h(2) : see declaration of 'A'

Share this post


Link to post
Share on other sites
You've not included the "FileManager" header, or provided a forward declaration of it, so the compiler doesn't know what a FileManager is.
Either #include "FileManager.h" (Or whatever the file is called), or add class FileManager; at the top of the file and #include "FileManager.h" in A.cpp.

Share this post


Link to post
Share on other sites
Add a forward declaration:

//a.h
class FileManager; /* Forward declaration */

class A
{
public:
FileManager *fmgr;
A();
~A();
int x;
int xx;
};

//a.cpp
#include "A.h"
/* Include header which contains definition of FileManager */

A::A()
{
this->fmgr = new FileManager;
}

~A::A()
{
delete fmgr;
}






Also, change this:

~A::A()
{
delete fmgr;
}




to this:

A::~A()
{
delete fmgr;
}



Share this post


Link to post
Share on other sites
The compiler is complaining that it does not know what a "FileManager" is. In a.h you need to include the header file that FileManager is declared in. Alternatively, you can put a forward declaration of the class FileMananger in a.h and include the other header in a.cpp. In any event, this article will likely help you.

Share this post


Link to post
Share on other sites
Alright I got that working I appreciate it. I have some questions about my FileManager Class. It can only save one int per file how do I make it so one file can hold all the stats for a character instead of having multiple files with just one number inside. Here is the code.


//FileManager.h
#include <fstream>
class FileManager
{
public:
std::ofstream ofile;
std::ifstream ifile;
int MyInt;
int GetInt;
char* cFile;
void SaveFile(char* Filename);
void LoadFile(char* Filename);
void CloseFile();
};


//FileManager.cpp
#include "FileManager.h"

void FileManager::SaveFile(char* Filename)
{
this->cFile = Filename;
ofile.open(cFile);
ofile.write((char*)&MyInt, sizeof(int));
ofile.close();
}

void FileManager::LoadFile(char* Filename)
{
this->cFile = Filename;
ifile.open(cFile);
ifile.read((char*)&GetInt, sizeof(int));
ifile.close();
}

Share this post


Link to post
Share on other sites
Perhaps you want something more along these lines:


//FileManager.h
//#include <fstream>
#include <string>
class SomeObject;

class FileManager
{
//public:
private:
//std::ofstream ofile;
//std::ifstream ifile;
//int MyInt;
//int GetInt;
//char* cFile;
std::string filename;
public:
FileManager(const std::string& fname);
void SaveFile(const SomeObject&);
void LoadFile(SomeObject&);
//void CloseFile();
};




One note, avoid making things that are only needed temporarily or by one function a member of the class.

Share this post


Link to post
Share on other sites
What are you hoping to gain by making a "file manager"? Why not just use the stream objects directly in the rest of the code? (Have you given any thought as to why there is no "file manager" class in the standard library?)

Share this post


Link to post
Share on other sites
Sure. What I'm saying is, two such classes already exist: they are called std::ifstream and std::ofstream, and they were designed by people with far more expertise and experience.

Sticking things together into another class doesn't "make things more object-oriented". A class' existence is justified by (a) the logic of bundling its data members together; (b) the invariants it can enforce, and (c) the effectively synthesized functionality.

A FileManager like this doesn't synthesize any new functionality, because calling SaveFile or LoadFile and then inspecting the read-into data member isn't any easier then just opening a stream and reading into a local variable. (More to the point, reading many data entries will require many calls to LoadFile, but doing it manually only requires one extra call to open the file, and then the same number of operations to read data.) It doesn't enforce any invariants; the "filename" is allowed to be anything, and it's the only really relevant data member. And it doesn't even make sense to hold on to an ofstream object and an ifstream object while the FileManager sits idle - never mind that the two streams don't really have anything to do with each other.

Here is a simple bit of functionality that you might find is useful:


template <typename T>
T read(istream& is) {
T result;
is >> result;
return result;
}


Now your calling code can be simplified in some cases:


// I don't need a temporary variable here:
// int x;
// cin >> x;
// cout << x;
cout << read<int>(cin);
// But be careful! You can't do that for more than one value at a time, because
// the order of evaluation is not guaranteed.

// May also be useful for loop controls:
do {
something();
} while (string("yY").find(read<char>(cin)) != string::npos);
// Although really, you should prefer to always read a line at a time from
// standard input, to avoid getting confused by "leftover" data.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this