sharing an ifstream obj within a class
I've got the following header and cpp file. Now, rather than having the fin only in the process method, I want it to be seen by every method in the class.
class ModelFile
{
private:
string path, name;
public:
ModelFile(string* ptr_filein);
void process(vector<SummaryType> & maxmin, list<string> & origTypeList, list<string> & sortedTypeList, list<ModelFile> & waitlist, string & outputprefix);
};
void ModelFile::process(vector<SummaryType> & maxmin, list<string> & userMasterTypeList, list<string> & sortedTypeList, list<ModelFile> & waitlist, string & outputprefix){
string filein = path+name;
ifstream fin;
fin.exceptions(ifstream::eofbit | ifstream::failbit | ifstream::badbit );
fin.open(filein.c_str());
...
}
I cut and pasted the "ifstream fin;" in both the private and public areas in the header such as below.
class ModelFile
{
private:
string path, name;
ifstream fin;
public:
ModelFile(string* ptr_filein);
void process(vector<SummaryType> & maxmin, list<string> & origTypeList, list<string> & sortedTypeList, list<ModelFile> & waitlist, string & outputprefix);
};
However, both vs2003 and vs2005 didn't like it. They each gave a different reason why that is.
vs2003:
C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\list(34) : error C2558: class 'ModelFile' : no copy constructor available or copy constructor is declared 'explicit'
No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\list(32) : while compiling class-template member function 'std::_List_nod<_Ty,_Alloc>::_Node::_Node(std::_List_nod<_Ty,_Alloc>::_Genptr,std::_List_nod<_Ty,_Alloc>::_Genptr,const _Ty &)'
with
[
_Ty=ModelFile,
_Alloc=std::allocator<ModelFile>
]
C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\list(108) : see reference to class template instantiation 'std::_List_nod<_Ty,_Alloc>::_Node' being compiled
with
[
_Ty=ModelFile,
_Alloc=std::allocator<ModelFile>
]
C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\list(107) : while compiling class-template member function 'std::list<_Ty>::_Nodepref std::list<_Ty>::_Nextnode(std::list<_Ty>::_Nodeptr)'
with
[
_Ty=ModelFile
]
ModelFile.cpp(143) : see reference to class template instantiation 'std::list<_Ty>' being compiled
with
[
_Ty=ModelFile
]
VS2005:
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>'
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
C:\Program Files\Microsoft Visual Studio 8\VC\include\ios(151) : see declaration of 'std::basic_ios<_Elem,_Traits>::basic_ios'
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
This diagnostic occurred in the compiler generated function 'std::basic_ifstream<_Elem,_Traits>::basic_ifstream(const std::basic_ifstream<_Elem,_Traits> &)'
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
you can't have a common ifstream object in a class? :confused:
[4120 byte] By [
rssmps] at [2007-11-11 7:21:35]

# 1 Re: sharing an ifstream obj within a class
of course you can. The problem lies somehwre else in your code.
The first error message is pretty clear: it says that you're trying to create a constainer of ModeFile but ModeFile has no public copy constructor.
BTW, your functions take many parameters. This is usually an indication of subotimal design. Either your functions do way too much than they should, or that these parameters aren't truly needed. That's besides the point.
In short, post your constructors' code.
Danny at 2007-11-11 21:02:29 >

# 2 Re: sharing an ifstream obj within a class
if I leave the ifstream object in the process method, it works fine. Why would making it a class wide object cause any problems dealing with copy constructor? So far, I've not needed to use a copy constructor.
as for the many parameters, two of them really should be static variables common to the class. The user supplies file with a list of names, the names should be read and then every ModelFile obj will use that same list.
HOwever, I didn't know how to make it static to the class.
All the examples I've seen are using int as the example. INitialization in this case is trivial.
What happens when a list needs to be static to the class? (as in the names supplied by the user? ) how do I initialize a list? Also, a static obj can't change in size right? so what happens when it's a list where the size is not known beforehand?
is there a good book that talks about the design aspect of a program?
rssmps at 2007-11-11 21:03:30 >

# 3 Re: sharing an ifstream obj within a class
I think you're confusing two unrelated concepts here: static data members and const data members. static data members ar shared by all instances of the same class, and they certainly can change their values. const data members aren't shared (unless dec;ared static) but they cannot change. Here's how you declare *and* define a static data member:
class C
{
static list<int> li; //declaration
};
list <int> C::li; //definition
There's no need to initialize the list because the list template has a default constructor. If you mean "pouplate", then you need to call one of the list member functions: push_back, assign etc.
As for the ifstream object: I still don't understand what is it that you're trying to do and where the compilation error occurs. You're probably doing somthing wrong, and the compiler reports an error, though not necessarily the correct error message.
Simply post more of the relevant code: how the data members are declared and what your Process member function does exactly.
Danny at 2007-11-11 21:04:30 >

# 4 Re: sharing an ifstream obj within a class
list <int> C::li; //definition
There's no need to initialize the list because the list template has a default constructor.
This was the missing key. All the examples that I found showed initialization(such as a static integer). So I was confused there.
As for the ifstream object: I still don't understand what is it that you're trying to do and where the compilation error occurs. You're probably doing somthing wrong, and the compiler reports an error, though not necessarily the correct error message.
Simply post more of the relevant code: how the data members are declared and what your Process member function does exactly.
as for this issue, I created a copy constructor to satisfy the compiler.
ModelFile::ModelFile(const ModelFile &existing)
{
path = existing.path;
name = existing.name;
positionFirstQuote = existing.positionFirstQuote;
positionLastQuote = existing.positionLastQuote;
positionLastSlash = existing.positionLastSlash;
positionFirstSlash = existing.positionFirstSlash;
textReadBuffer = existing.textReadBuffer;
fileInputStream = existing.fileInputStream;
}
but when I did this, I got:
error C2582: 'operator =' function is unavailable in 'std::basic_ifstream<_Elem,_Traits>'
with
[
_Elem=char,
_Traits=std::char_traits<char>
]
If I take out that line completely than it compiles fine.
So:
what's the right way to deep copy ifstream object?
when are you required to have an copy constructor?
rssmps at 2007-11-11 21:05:30 >

# 5 Re: sharing an ifstream obj within a class
OK, so you want to know how to copy two file streams. Actually, it's impossible for many good reasons. In most cases, this can be quite dangerous because it could lead to data corruption. Think fo rexample about the destructor of such an object -- when the identical fstream objects' destructors execute, they will close the same file twice, which is an error. So the real question is why you need to copy the file object to a different object instead of sharing the same file stream object. Obviously, you can't have two FileMode objects that access the same file simultaneously. If however you want to do that, my advice is to use a reference data member and bind it during construction to an external file stream object. This way you don't have two file stream objects but only one.
As for the copy constructor question: your program doesn't need it as a matter of fact. As long as all the data members in FileMode are pure objects: std::string, std::list, ints, etc. you don't need to write a copy ctor because the compiler-generated copy ctor will do the right thing anyway. However, make sure that your class doesn't have non-copyable objects (file streams for instance) or pointers.
Danny at 2007-11-11 21:06:30 >

# 6 Re: sharing an ifstream obj within a class
so in my class, the only thing hanging up the compiler was the ifstream object?
yet, it's a non-copyable object....so I could have had an empty copy constructor?
#ifndef ModelFile_h
#define ModelFile_h
using namespace std;
class ModelFile
{
private:
// member data
string path, name;
int positionFirstQuote, positionLastQuote, positionLastSlash,positionFirstSlash;
void extractPathName(string & filein);
list<string> textReadBuffer;
ifstream fileInputStream;
public:
//constructor
ModelFile(string* ptr_filein);
void process(vector<SummaryType> & maxmin, list<ModelFile> & waitlist, string & outputprefix);
string getPath();
string getName();
list<string> getNextCompleteCardData(ifstream fin);
static list<string> origUserInputTypeList,sortedTypeList;
ModelFile(const ModelFile &existing);
};
#endif
oh, and by the use of two static objects, I was able to cut down on the parameters required for the process method.
rssmps at 2007-11-11 21:07:29 >

# 7 Re: sharing an ifstream obj within a class
yes, if it hasn't been for the non-copyable file stream, you wouldn't needed a copy constructor. But I would also change all your list<string> to vector <string> and return the string vetcor by reference, not by value, in the function: list<string> getNextCompleteCardData(ifstream fin);
BTW, I suspect that passing fin by value is another cause of compilation errors. In any case, it's a bug. You want to pass it by reference:
vector<string> & getNextCompleteCardData(ifstream & fin);
Danny at 2007-11-11 21:08:27 >
