Using a Class within a Class.

Started by
7 comments, last by Zahlman 15 years, 5 months ago
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'
Advertisement
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.
Add a forward declaration:
//a.hclass 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;}
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.
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();}
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.
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?)
I was to write a re usable class for multiple projects I am working on that need to save and load values for the player to continue.
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.

This topic is closed to new replies.

Advertisement