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.