• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 993
  • Last Modified:

Visual Studio Error C2248

Greetings -- Please consider the following contentents of file TMDefinition.h, and how it might be leading to the intractible Error C2248 (described below) in Visual Studio.

----------------------------------------------------------------------

#include <iostream>
#include <fstream>
#include "StringVector.h"

using namespace std;

class TMDefinitionStream : public ifstream
{
private:
    StringVector keywords;
    string lastKeywordRead;
public:
    TMDefinitionStream(string fileName);        // This is the nexus of Error C2248
    bool Next_Word(string& toRead, bool& isKeyWord);
    string Last_Keyword_Read();      
};

----------------------------------------------------------------------------

Error   1   error C2248: 'std::basic_ios<_Elem,_Traits>::basic_ios' : cannot access private member declared in class 'std::basic_ios<_Elem,_Traits>'  c:\users\gary\documents\visual studio 2010\projects\tmree\tmree\tmdefinitionstream.h      20      1      TMREe

----------------------------------------------------------------------------

1. This is the only error in the entire project.

2. By commenting out the several elements of the class definition, I find that the error seems to be centered on the constructor.  Without a constructor, the compiler complains about lots of OTHER things, but not C2248.  With the constructor, there will always be a C2248.  This is despite the fact that the error message itself points to line 20, which is the closing brace of the class definition.

3. The entire class definition is perfectly fine IN ITS CURRENT FORM if moved to main.cpp.  In that case, I had to alter the name of the class slightly, but that's all.  This leads me to think that perhaps something that *follows* TMDefinition.h is tripping it up.  That may be, but in the entire project TMDefinition.h is never the *last* header file called out.  I guess what I would be looking for here is if anyone can image what cockamamee thing might be in the next header file - that only comes up when this header file preceeds it - that would result in error E2248.

This project is an implementation of a Turing Machine for a college class I am taking.  One of the rules is that we can use no library other than the standard library.  Therefore, I cannot accept any solution that would violate that rule.  Beyond that, I started this as an "empty" project to make it as standard C++ as possible.  It will eventually have to be ported to a G++ compiler running on Ubuntu.

**** Many Thanks *****
0
NonComposMentis
Asked:
NonComposMentis
  • 5
  • 4
  • 2
  • +1
1 Solution
 
jkrCommented:
What does 'StringVector.h' look like? The snippet you gave - with only small changes - compiles fine:

#include <iostream>
#include <fstream>
//#include "StringVector.h"

using namespace std;

class TMDefinitionStream : public ifstream
{
private:
    //StringVector keywords;
    string lastKeywordRead;
public:
    TMDefinitionStream(string fileName);        // This is the nexus of Error C2248
    bool Next_Word(string& toRead, bool& isKeyWord);
    string Last_Keyword_Read();      
};

Open in new window


All that VC++ 10 complains about the above is that 'main()' is missing (well, for sure), which makes me think that there is an issue with the aforementioned header file...
0
 
NonComposMentisAuthor Commented:
Thanks, jkr:  here is StringVector.h

#ifndef StringVector_h
#define StringVector_h

#include <string>	// #include<string> must come before #include <vector>
#include <vector>

using namespace std;

class StringVector : public vector<string>
{
private:
	bool isCaseSensitive;

public:
	void Case_Sensitivity(bool isCaseSensitive);
	bool Is_In_Vector(const string& testString) const;
	bool Enqueue_Unique(const string& addString);
};

#endif

Open in new window

0
 
jkrCommented:
Nope, no way, won't get the error with the above - not even a warning...
0
Cloud Class® Course: Certified Penetration Testing

This CPTE Certified Penetration Testing Engineer course covers everything you need to know about becoming a Certified Penetration Testing Engineer. Career Path: Professional roles include Ethical Hackers, Security Consultants, System Administrators, and Chief Security Officers.

 
NonComposMentisAuthor Commented:
Well, OK.  As I stated originally, I don't get the error either if I take the whole business and move it to main.cpp.  There is something about *where* it is or how it is used.  The compiler's message is not that helpful to me.  I was hoping perhaps someone else could decipher "cannot access private member declared in class 'std::basic_ios<_Elem,_Traits>'".
0
 
ZoppoCommented:
Hi NonComposMentis,

I guess the problem is somewhere else in your code, I think the base class ifstream cannot be copied - do you anywhere create a copy of a TMDefinitionStream instance (can even be a function call where such an instance is passed by value instead of by reference). For any reason in this case VS 2010 shows an error in the class declaration without hint where the problem comes from.

I.e. take a look at this code:
class TMDefinitionStream  : public std::ifstream
{
public:
	TMDefinitionStream ( std::string fileName ) {}
};
TMDefinitionStream t1( "test.txt" );

Open in new window

This should compile fine - now add this line:
TMDefinitionStream t2( t1 );

Open in new window

Now VS 2010 reports the same error.

Hope that helps,

ZOPPO
0
 
ZoppoCommented:
... the same happens for code like
TMDefinitionStream t2 = t1;

Open in new window

or
void foo( TMDefinitionStream t2 ) {}
...
foo( t1 );

Open in new window

0
 
ZoppoCommented:
... and, JFI, another possibility is returning a TMDefinitionStream - I once had the problem when I ported code from VC++ 6 to VS 2008, there was an overloaded shift operator like this:
class TMDefinitionStream  : public std::ifstream
{
public:
	TMDefinitionStream TMDefinitionStream::operator >> ( std::vector< std::string > v )	{ return *this; }
};

Open in new window

This compiled (and, at least how we used it, it worked) fine in VC++ 6, in VS 2010 I got the same error 2248 without any hint where the problem comes from (in a file with > 2000 lines).

In VS 2010 this has to be implemented like this:
class TMDefinitionStream  : public std::ifstream
{
public:
	TMDefinitionStream& TMDefinitionStream::operator >> ( std::vector< std::string > v )	{ return *this; } // return value must be a reference
};

Open in new window

ZOPPO
0
 
NonComposMentisAuthor Commented:
Just about every class in the project gets a turn at the "Turing machine definition stream", and yes, some of them were passed copies instead of references.  When I started this project I thought objects were *always* passed by reference.  Guess not in this language.  Many thanks!
0
 
ZoppoCommented:
Yes, in C/C++ values can be either passed by value or by reference (in C only possible with pointers) - i.e. take a look here about more info:
http://www.cplusplus.com/doc/tutorial/functions2/
http://en.wikipedia.org/wiki/Evaluation_strategy

Have a nice day,

best regards,

ZOPPO
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> using namespace std;

Unrelated to the problem but... having this in a header file is a really bad idea and just a problem waiting to happen. Trust me, you don't want to go polluting all your code with a namespace via a header file.
0
 
NonComposMentisAuthor Commented:
So inside the header files, I just use "std::" everywhere?  I was kind of under the impression I had to use "using namespace std;" in each *file* that it was used in.  In other words, the header files would not "pollute" the cpp files, as you say.  But you're right.  I just tested it and calling out the namespace is unnecessary in the cpp file if it is done in the header.  That being the case, I can see the potential for conflicts.  Thanks!
0
 
evilrixSenior Software Engineer (Avast)Commented:
>> So inside the header files, I just use "std::" everywhere?
Exactly.

>>  I was kind of under the impression I had to use "using namespace std;" in each *file*
Nope. Only where you want to import the namespace.

>>  In other words, the header files would not "pollute" the cpp files, as you say
They absolutely will and can result in some very hard to track down compiler time errors.

>> calling out the namespace is unnecessary in the cpp file if it is done in the header.
You should only have the using namespace clause in the .cpp file; NEVER the header.

"Namespace Rule #1: Avoid using directives entirely, especially in header files.

The reason for Rule #1 is that using directives cause wanton namespace pollution by bringing in potentially huge numbers of names, many (usually the vast majority) of which are unnecessary. The presence of the unnecessary names greatly increases the possibility of unintended name conflicts--not just in the header itself, but in every module that #includes the header. I find it helpful to think of a using directive as a marauding army of crazed barbarians that sows indiscriminate destruction wherever it passes--something that by its mere presence can cause "unintended conflicts," even when you think you're allied with it."

http://www.gotw.ca/publications/migrating_to_namespaces.htm

FWIW: GOTW is a very worthwhile read (it's quite large but full of very very helpful C++ tips).
0
 
NonComposMentisAuthor Commented:
Thanks, evilrix.  I read the entire page you referenced.  I like that they show you how to do all the stuff they're trying to talk you out of!  Very nice.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Cloud Class® Course: Microsoft Exchange Server

The MCTS: Microsoft Exchange Server 2010 certification validates your skills in supporting the maintenance and administration of the Exchange servers in an enterprise environment. Learn everything you need to know with this course.

  • 5
  • 4
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now