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.