This is my sample code:
#include <iostream>
#include <string>
using namespace std;
class MyClass
{
string figName;
public:
MyClass(const string& s)
{
figName = s;
}
const string& getName() const
{
return figName;
}
};
ostream& operator<<(ostream& ausgabe, const MyClass& f)
{
ausgabe << f.getName();
return ausgabe;
}
int main()
{
MyClass f1("Hello");
cout << f1;
return 0;
}
If I comment out #include <string> I don't get any compiler error, I guess because it's kind of included through #include <iostream>. If I "right-click --> Go to Definition" in Microsoft VS they both point to the same line in the xstring file:
typedef basic_string<char, char_traits<char>, allocator<char> >
string;
But when I run my program, I get an exception error:
0x77846B6E (ntdll.dll) in OperatorString.exe: 0xC00000FD: Stack overflow (Parameter: 0x00000001, 0x01202FC4)
Any idea why I get a runtime error when commenting out #include <string>? I'm using VS 2013 Express.
Indeed, very interesting behavior.
Any idea why I get I runtime error when commenting out #include <string>
With MS VC++ compiler the error happens because if you do not #include <string> you won't have operator<< defined for std::string.
When the compiler tries to compile ausgabe << f.getName(); it looks for an operator<< defined for std::string. Since it was not defined, the compiler looks for alternatives. There is an operator<< defined for MyClass and the compiler tries to use it, and to use it it has to convert std::string to MyClass and this is exactly what happens because MyClass has a non-explicit constructor! So, the compiler ends up creating a new instance of your MyClass and tries to stream it again to your output stream. This results in an endless recursion:
start:
operator<<(MyClass) ->
MyClass::MyClass(MyClass::getName()) ->
operator<<(MyClass) -> ... goto start;
To avoid the error you need to #include <string> to make sure that there is an operator<< defined for std::string. Also you should make your MyClass constructor explicit to avoid this kind of unexpected conversion.
Rule of wisdom: make constructors explicit if they take only one argument to avoid implicit conversion:
class MyClass
{
string figName;
public:
explicit MyClass(const string& s) // <<-- avoid implicit conversion
{
figName = s;
}
const string& getName() const
{
return figName;
}
};
It looks like operator<< for std::string gets defined only when <string> is included (with the MS compiler) and for that reason everything compiles, however you get somewhat unexpected behavior as operator<< is getting called recursively for MyClass instead of calling operator<< for std::string.
Does that mean that through #include <iostream> string is only included partly?
No, string is fully included, otherwise you wouldn't be able to use it.
The problem is that your code is doing an infinite recursion. The streaming operator for std::string (std::ostream& operator<<(std::ostream&, const std::string&)) is declared in <string> header file, although std::string itself is declared in other header file (included by both <iostream> and <string>).
When you don't include <string> the compiler tries to find a way to compile ausgabe << f.getName();.
It happens that you have defined both a streaming operator for MyClass and a constructor that admits a std::string, so the compiler uses it (through implicit construction), creating a recursive call.
If you declare explicit your constructor (explicit MyClass(const std::string& s)) then your code won't compile anymore, since there is no way to call the streaming operator with std::string, and you'll be forced to include the <string> header.
EDIT
My test environment is VS 2010, and starting at warning level 1 (/W1) it warns you about the problem:
warning C4717: 'operator<<' : recursive on all control paths, function will cause runtime stack overflow
Related
I created this code:
Main.cpp
#include <iostream>
#include "Quote.h"
int main()
{
derived().print(std::cout);
getchar();
return 0;
}
Quote.h
#pragma once
#include <string>
class base {
public:
std::string name() { return basename; }
virtual void print(std::ostream &os) { os << basename; }
private:
std::string basename = "abc";
};
class derived : public base {
public:
void print(std::ostream &os) { base::print(os); os << " " << i; }
private:
int i = 0;
};
If I don't include the iostream header file in Main.cpp, as expected, std::cout is not recognized. My question is: Why there's no problem with the use of std::ostream in Quote.h if iostream is not included?. Either cout as ostream are defined in the aforementioned library, why the cout use is a problem and ostream not?
I'm using VS 2017, in case this info is important.
All existing answers concentrate on #include <string>. I'd like to point at another side. Consider slightly modified version:
quote.h:
#pragma once
// uncomment to get an analog of original example
// #include <string>
struct Quote {};
std::ostream& operator<<(std::ostream& os, Quote const&)
{
return os << "quote\n";
}
main.cpp:
#include <iostream>
#include "quote.h"
int main()
{
std::cout << Quote{};
}
As you see #include <string> is commented out, quote.h still doesn't include iostream and the program still compiles. It does because only source files (.cpp, or translation units) are directly compiled. Headers are literally included. Now if we literally include quote.h in main.cpp we get:
#include <iostream>
// uncomment to get an analog of original example
// #include <string>
struct Quote {};
std::ostream& operator<<(std::ostream& os, Quote const&)
{
return os << "quote\n";
}
int main()
{
std::cout << Quote{};
}
(online)
It's what actually gets compiled. Notice everything is alright here, #include <iostream> before std::ostream usage.
And as was correctly pointed in comment to another answer, this is an example why it's important to always maintain self-sufficient headers that include all headers they depend on.
As #Evgeny pointed out in the comment, please check recommendations about organising our includes.
The header <string> declares an output operator using std::ostream. It seems the implementation you are using does so in a way making std::ostream generally available.
The C++ standard defines which headers make which declarations available at least. It doesn’t prohibit against additional names being made available. Different implementations may choose to not make the declarations available. I have tried making strictly only mandated declarations available in my implementation but this turns out to be not quite as simple as it sounds.
You include <string> in your header file. If you go to the string header you will see the first lines as (in VS2017):
// string standard header
#pragma once
#ifndef _STRING_
#define _STRING_
#ifndef RC_INVOKED
#include <istream> <----- here
#include <xstring_insert.h>
and going to the istream header:
// istream standard header
#pragma once
#ifndef _ISTREAM_
#define _ISTREAM_
#ifndef RC_INVOKED
#include <ostream> <-- here
which I think already answers your question. However, this is implementation dependent and you should not rely on this but include explicitly the iostream header.
The header <string> provides the extraction and insertion operators for std::string, so it has to make sure that std::ostream is at least forward-declared; your code only uses a reference to ostream, for which a forward declaration suffices, plus the aforementioned insertion operator, which is correctly declared.
So, strictly speaking, all that is needed by your header is already provided by the header <string>, although I'd probably explicitly include <iosfwd> for clarity.
Why there's no problem with the use of std::ostream in Quote.h if <iostream> is not included?
<iostream> get #included indirectly.
It's best not to rely on such indirection #includes. You can't count on it being true on all platforms. It may even change from debug build to release build.
When you want to use a class or a function, it's best to lookup the standard for the header that's supposed to provide the definition of the class and the declaration of the function, and #include the header directly in your file.
This question already has answers here:
C++, good old LNK1169 (and LNK2005) errors
(3 answers)
Closed 5 years ago.
I'm learning c++ and trying to practice translation units and other things at once, but I'm getting the errors listed on the title. This program is for learning purposes and I've tried to explain what each header and implementation file is suppose to do.
--------CString.h--------
#ifndef CSTRING_H
#define CSTRING_H
#include <iostream>
namespace w1
{
class CString
{
public:
char mystring[];
CString(char cstylestring[]);
void display(std::ostream &os);
};
std::ostream &operator<< (std::ostream &os, CString &c)
{
c.display(os);
return os;
}
}
#endif
--------process.h-------- prototype for process function
void process(char cstylestring[]);
--------CString.cpp--------
To receive a C-style string in constructor and truncate it by taking the first three characters and storing it in mystring to be later displayed through the function display()
#include <iostream>
#include "CString.h"
#define NUMBEROFCHARACTERS 3
using namespace w1;
w1::CString::CString(char stylestring[])
{
if (stylestring[0] == '\0')
{
mystring[0] = ' ';
}
else
{
for (int i = 0; i < NUMBEROFCHARACTERS; i++)
{
mystring[i] = stylestring[i];
}
}
//strncpy(mystring, stylestring, NUMBEROFCHARACTERS);
}
void w1::CString::display(std::ostream &os)
{
std::cout << mystring << std::endl;
}
--------process.cpp-------- receives a C-style string and creates a CString object and then display the possibly truncated version of the c-style string by operator overloading.
#include "process.h"
#include "CString.h"
#include <iostream>
using namespace std;
void process(char cstylestring[])
{
w1::CString obj(cstylestring);
std::cout << obj << std::endl;
}
--------main.cpp-------- Testing purposes by sending a C-style string to process function.
#include <iostream>
#include "process.h"
using namespace std;
int main()
{
char themainstring[] = "hiiiii";
process(themainstring);
return 0;
}
The << operator is defined multiple time because you define it in an header file that is include from multiple source files.
Either add inline modifier so that only one copy will be kept or move the definition in one source file (and only keep the declaration in the header file).
As I have mentioned in my comment, the program would crash at run time because no memory is allocated for mystring. If it should be 4 characters long maximum, then you could simply add 4 inside the square bracket as in:
char mystring[4];
Otherwise, if you need variable size, then using something like std::vector might make sense as you would avoid explicit memory management.
Update:
My original answer was complete but since you don't seem to properly understand it, I have added extra details...
I am talking of the following definition in CString.h:
std::ostream &operator<< (std::ostream &os, CString &c)
{
c.display(os);
return os;
}
Both process.cpp and main.cpp include the file CString.h which contains that definition twice (once when compiling each of these 2 files).
so I've got a project where I am inserting user entered data into classes. So I've overloaded the >> operator. Because I have classes with similar structures, I made the overload a template to try to save time. Making this template overload a friend of the classes seems to work, as I get no compile errors.
My ClassDefs.h:
// ClassDefs.h
using namespace std;
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <tuple>
#include <map>
#include <typeinfo>
class measurement {
//friends
template<class measT> //measT are other similar measurement classes
friend istream & operator >> (istream&, measT&);
private:
string words;
public:
//constructors and things like that here
};
template<class measT>
istream& operator >> (istream& is, measT& meas) {
//a series of checks to ensure user entry is valid
//enter user entry into private data
//e.g.
string line;
getline(is,line);
meas.words = line;
return is;
}
The problem comes when using cin >> foo in main - I get a warning caption saying "more than one operator >> matches these operands". Accompanied by:
error C2593: 'operator >>' is ambiguous
This makes sense, but my crude understanding of overloads was that they allow you to use different types with that operator and the compiler "understands" which definition to use for each situation.
My main.cpp:
// main.cpp
#include "ClassDefs.h"
int main(){
string entry;
cin >> entry;
^^ error here
return 0;
}
I have looked around and seen things involving explicit, inline, namespace (my using namespace std; seems dodgy) but I haven't seen anyone use this template overload arrangement and have this problem. I'm using Visual Studio 2015 Community.
Any help or advice would be greatly appreciated :)
So I solved this partially with the help of #user4581301 - I really needed to keep the >> overload a template so that I could use that parameter for a template exception class inside it.
It has become a bit convoluted but I thought I'd share in case anyone else is having issues overloading operators with templates.
Firstly I changed measurement from an abstract base class to a base class (so that it could be used as a template parameter) and changed the friend declaration inside to:
//ClassDefs.h
template <class measT>
friend istream& operator >> (istream&, measurement&);
Where measT was the type of measurement involved, to be used as the parameter for the exception class.
Then later on in the header file, >> was overloaded with the definition:
//ClassDefs.h
template<class measT>
istream& operator >> (istream& is, measurement& meas) {
//take user input
//do checks on it, throw Exception<measT> depending on which set of
exceptions are relevant
}
And most importantly I wasn't sure how to use an operator with a template parameter but it turns out you can do it explicitly:
//ClassDefs.h
template<class measT>
measT userNewMeas() { //function to take user input and make into a type
// of measurement
try { ::operator>><measT> (cin,newMeas); }
catch (Exception<measT>& error) {
cout << error << endl; // this output depends on which exception
// was called
}
And now I can use template userNewMeas() in main.cpp with template >> and template Exception. The goal is probably hard to see for everyone but I was trying to overload >> for any measurement type, and have one Exception class containing different error messages to be thrown depending on which measurement was being entered.
I got a strange problem with my program. So in the header I got something like this:
#ifndef SET1_INCLUDED
#define SET1_INCLUDED
#include <iostream>
using namespace std;
typedef std::string ItemType;
class Set1{
public:
------some public constructor and method in here-------
private:
ItemType setMember[100];
}
in 1 part of my function in the Set1.cpp file I got something like this :
if (setMember[i] == "foo") {exist = true;}
In this case, I got an error message that says "no operator found which takes a left-hand operand of type 'ItemType' ". However, if I change the std::string in the typedef into int or unsigned long, and change "foo" to some random number, the code works perfectly. Any suggestion? thx
You are missing the header file <string>, which means that you don't have all of the global operator == definitions visible in your program. This is likely the case of your problem.
To fix this, try adding in this line:
#include <string>
Hope this helps!
You need to include string header file to bring relative types and operator to scope.
#include <string>
Note:
It's bad coding practice to pull in everything from std namespace in header file.
//using namespace std;
Could any body offer me any reason about that?
If we do it like that, what's the outcome? Compile error?
The problem is that static initialization isnt just initialization, it is also definition. Take for example:
hacks.h :
class Foo
{
public:
static std::string bar_;
};
std::string Foo::bar_ = "Hello";
std::string GimmeFoo();
main.cpp :
#include <string>
#include <sstream>
#include <iostream>
#include "hacks.h"
using std::string;
using std::ostringstream;
using std::cout;
int main()
{
string s = GimmeFoo();
return 0;
}
foo.cpp :
#include <string>
#include <sstream>
#include <iostream>
#include "hacks.h"
using std::string;
using std::ostringstream;
using std::cout;
string GimmeFoo()
{
Foo foo;
foo;
string s = foo.bar_;
return s;
}
In this case, you can't initialize Foo::bar_ in the header because it will be allocated in every file that #includes hacks.h. So there will be 2 instances of Foo.bar_ in memory - one in main.cpp, and one in foo.cpp.
The solution is to allocate & initialize in just one place:
foo.cpp :
...
std::string Foo::bar_ = "Hello";
...
It is just a limitation in the language it self. Hopefully, when C++0x becomes reality, this limitation would go away.
I think this page gives a somehow good reason:
One of the trickiest ramifications of
using a static data member in a class
is that it must be initialized, just
once, outside the class definition, in
the source file. This is due to the
fact a header file is typically seen
multiple times by the compiler. If the
compiler encountered the
initialization of a variable multiple
times it would be very difficult to
ensure that variables were properly
initialized. Hence, exactly one
initialization of a static is allowed
in the entire program.