Sign in to follow this  
Ehrys

Problem with fstream.

Recommended Posts

Currently got a weird looking problem with fstream.
1>C:\Program Files\Microsoft Visual Studio 8\VC\include\fstream(675) : error C2248: 'std::basic_ios<_Elem,_Traits>::basic_ios' : cannot access private member declared in class 'std::basic_ios<_Elem,_Traits>'
1>        with
1>        [
1>            _Elem=char,
1>            _Traits=std::char_traits<char>
1>        ]
1>        C:\Program Files\Microsoft Visual Studio 8\VC\include\ios(151) : see declaration of 'std::basic_ios<_Elem,_Traits>::basic_ios'
1>        with
1>        [
1>            _Elem=char,
1>            _Traits=std::char_traits<char>
1>        ]
1>        This diagnostic occurred in the compiler generated function 'std::basic_ifstream<_Elem,_Traits>::basic_ifstream(const std::basic_ifstream<_Elem,_Traits> &)'
1>        with
1>        [
1>            _Elem=char,
1>            _Traits=std::char_traits<char>
1>        ]

The class header "Unit.h":
#pragma once

#include <iostream>
#include <fstream>
#include <cmath>
#include <vector>
#include "..\Vectors.h"
#include "BulletManager.h"

using namespace std;

struct sUnitInfo
{
	int					Health;
	unsigned int		Speed;
	unsigned int		Power;
	unsigned short		UnitType;

	double				VisibleRange;
	double				FiringRange;
	double				RateOfFire;
};

class CUnit
{
public:
	CUnit(unsigned int UnitID, CBulletManager *inBulletManager);
	~CUnit(void);

	void			Initialise(sUnitInfo inInfo);

	unsigned int	GetID() { return m_ID; }
	unsigned short	GetType() { return m_Type; }

	CVector2d		GetPosition();// return CVector2d(m_RealX, m_RealY); } //m_Position; }
#ifdef _DEBUG
	double			GetRealX() { return m_RealX; }
	double			GetRealY() { return m_RealY; }
#endif
	double			GetShootingRange() { return m_FiringRange; }
	double			GetViewingRange() { return m_VisibleRange; }
	double			GetFirepower() { return m_Power; }

	bool			InflictDamage(double Amount);
	void			Shoot(CVector2d TargetPosition);

	void			SetRoute(vector<CVector2i>* Route);
	void			SetPosition(CVector2d inPosition);
	CVector2i		NextDestination() { return m_Route[0]; }

	void			Update(double inFrameTime);
private:
	void			Move();
	void			Animate(){ return; }
	void			Draw(){ return; }

	bool				Initialised;
	unsigned int		m_ID;
	unsigned int		m_Power;
	unsigned int		m_Speed;
	double				m_Health;
	unsigned int		m_TargetID;

	unsigned short		m_Type;
	unsigned short		m_Formation;

	double				m_VisibleRange;
	double				m_FiringRange;
	double				m_RateOfFire;
	double				m_FireTimer;

	double				m_FrameTime;
	double				m_RealX;
	double				m_RealY;
	CVector2d			m_Position;
	vector<CVector2i>	m_Route;

	bool				m_isEnemy;
	bool				m_isFiring;
	bool				m_HasRoute;

	CBulletManager*		m_BulletManager;
	ifstream			UnitLog;
};

I would have edited this down a little but I'm unsure how it would affect the declaration of fstream. This isn't the only class where I'm using the fstream object. I have it declared exactly the same in 3 other classes. Specifically in "FileReader.h"
#pragma once
#include <iostream>
#include <fstream>
#include <vector>

#include "MapData.h"
#include "Unit.h"

using namespace std;

typedef vector<unsigned short> MapY;
typedef vector<MapY> Map;

class CFileReader
{
public:
	CFileReader(void);
	~CFileReader(void);

	bool			LoadMap(char* Mapname, CMapData* MapData);
	bool			SaveMap(char* Mapname, CMapData* MapData);
	bool			LoadUnitInfo(vector<sUnitInfo>* UnitInfo);
//	bool			SaveUnit();
private:
	fstream Logger;
};

Which works perfectly. fstream& UnitLog; doesn't work fstream* UnitLog; doesn't work ifstream UnitLog; (or any variation */&) doesn't work ofstream UnitLog; (or any variation */&) doesn't work I have tried creating a completely empty class and including it there instead with "Logger.h"
#pragma once

#include <iostream>
#include <fstream>

#using namespace std;

class CLogger
{
public:
       CLogger();
       ~CLogger();
private:
       fstream Log;
};

Which also fails. So I'm at a loss now. I don't know what is causing the error. Any help is greatly appreciated and urgently required (as this is my Final Year Project for University) >.< [Edited by - Ehrys on March 7, 2007 8:29:55 AM]

Share this post


Link to post
Share on other sites
I can't see any problem with your code. Try removing the iostream inclusion - you only need that for certain streams and manipulators. If you do need it in there, try re-ordering the header inclusions. Or move the fstream member from the private block to being public.

Share this post


Link to post
Share on other sites
Tried what you suggested, still same error. Is there a limit as to how many instances you can have per application?

Just a note, removing iostream has changed the line number of the error in fstream.h from 675 to 933. But I don't know enough about the fstream internals on Win32 to debug.

Share this post


Link to post
Share on other sites
"#using namespace std;" <--- The hell?

Quote:
1> This diagnostic occurred in the compiler generated function 'std::basic_ifstream<_Elem,_Traits>::basic_ifstream(const std::basic_ifstream<_Elem,_Traits> &)'
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]


This means you're trying to copy an std::ifstream somewhere, which is illegal. If there was more to your error message after this, please post it, and the source code that it references.

Share this post


Link to post
Share on other sites
Everything was in the OP

Also, I use the std namespace because I get fed up of writing std:: everywhere. I don't have another namespace, nor am I using statics. so not using it would have been a waste of time. Unless you know a better way.

Also, the code only generates the error when I declare the object
"fstream UnitLog;"

There has been no initialisation anywhere in the code. As I previously stated trying to use references and pointers also failed to work, giving me the same error as before.

EDIT:

I just thought of something. Could it be the way that I'm declaring/instantiating the CUnit class in my Database? I can't open VS atm however it goes along the lines of:


1. Create a vector of CUnit.
2. Resize vector to number of CUnit that will be inited.
3. Load unit info from disk.
4. DO WHILE : Number of units created is less than the specified amount.
5. Create a variable of type CUnit
6. Initialise variable with UnitInfo "CUnit::Initialiase(sUnitInfo UnitInfo);"
7. Push unit onto vector. (vector::push_back())
8. LOOP





Header File:

vector<CUnit> m_UnitList;

CPP File:

CDBase::GenerateUnits(unsigned int numGrunts)
{
for(unsigned int Counter = 0; Counter < numGrunts; Counter++)
{
CUnit Grunt(Counter + 1, m_BulletManager);
Grunt.Initialise(m_UnitInfo[0]);
m_UnitList.push_back(Grunt);
}

for(unsigned int Counter = numGrunts; Counter < numGrunts + (numGrunts / 5); Counter++)
{
CUnit General(Counter + 1, m_BulletManager);
General.Initialise(m_UnitInfo[1]);
m_UnitList.push_back(General);
}
}



That's all there is.

Please forgive my use of "Counter" but I was in a rush ;)

[Edited by - Ehrys on March 7, 2007 1:48:31 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by MaulingMonkey
This means you're trying to copy an std::ifstream somewhere, which is illegal. If there was more to your error message after this, please post it, and the source code that it references.


Right. Perhaps an implicit copy constructor? Are you doing something like this somewhere?


CLogger log1;
CLogger log2 = log1;




If so, you might need to write your own copy constructor.

EDIT: Seeing your edit above, that's probably it. Using std::vector<CUnit> means that you're putting units into the vector by value, which means the ones in the vector are copied from the ones you have. Try using a std::vector<CUnit*> instead, but watch out - you're going to have to deal with allocating and deleting those objects if you do.

Share this post


Link to post
Share on other sites
No, I'm simply trying to declare it.

In that particular class, I have not got any more code relating to fstream or the variable I am trying to create.
In reply to justinian's edit -
Yeah I guess that makes sense. Completely forgot that it would be making copies that way >.<

I'll begin recoding and let you know how it goes :)

Thanks for the help so far everyone.

Share this post


Link to post
Share on other sites
Problem solved. Now I just have to re-write my application to use pointers, heh.

Thanks for the help.

While I'm here I'm going to hijack my own thread. Anyone know where I can get some good info about distributed networking patterns/models. Preferably code based ones. Win32 or Linux, doesn't bother me :)

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Don't place "using namespace std" in header files. It will mess stuff up real good when you least expect it.

Share this post


Link to post
Share on other sites
Howcome?

Sorry I'm one of those people that like to understand the principle rather than just make do because "it does". ^.^

Share this post


Link to post
Share on other sites
Quote:
Original post by Ehrys
Problem solved. Now I just have to re-write my application to use references, heh.


Fixed.

As noted, you can't copy a stream object, for the reason that allowing this would allow chaos to ensue. For fstreams, copied objects would refer to the same file on disk, but have independent read/write positions. That's bad enough, but consider what happens with multiple copies of, say, std::cin :)

Also, it is probably a bad idea to have streams as members of an object. Because they'll prevent your object from being copyable.

That said, you *can* use for example a boost::shared_ptr to the stream (since this will never attempt to copy the stream, but only increment a reference count), but it's still usually a bad idea to have one as a data member, because it's harder to understand the scope/lifetime that way - and in the usual case, it's just a waste of memory in the struct for something that could just be a local variable in one (or some) of the member functions.

The FileReader (what's with the C prefixes, BTW?) works because nothing ever attempts to copy one, naturally. For logging, though... well, does it really make sense to build in the flexibility for each unit to be able to log to its own file? :)

Share this post


Link to post
Share on other sites
Quote:
Original post by Ehrys
Howcome?

Sorry I'm one of those people that like to understand the principle rather than just make do because "it does". ^.^


It relates to the fundamental problem that the processor is an evil text-substitution-engine hack.

When you put a using-declaration into a header, then everyone that #includes the header gets that using-declaration pasted into their code. If it's pasted at top level, that means they now have a using-declaration at top level at the beginning of their file, which could change the way that names are looked up in that source file, in a highly unexpected manner.

This typically causes the developer of the source file in question to grumble, spend hours looking in the wrong places to find the real problem and make it compile, slap him/herself on the head upon finding it, spend some more time confirming what has happened in detail, and then hunt down the developer of the header file in question and stab him/her in the eye with a fork. (If this is a one-person project, that means you get hurt *twice*.)

Share this post


Link to post
Share on other sites
Thanks for the explanation :)

The reason I use "C" prefix is because it's habit. Nothing more. I was taught the old hungarian notation and it's something that seems to have stuck unfortunately.

The reason I need each unit to include its own logger is because they are going to be used in multi-threading. I want to enable simultaneous writes (to different files) so I can see how the processes are interacting, how the locks are working and mainly so I can whack it in my 400 page report at the end as some kind of performance analysis.

PS. I promptly removed all references to using namespace std; in the header files. I don't like forks :(

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