10

I have a class like this one:

class Test{
public:
  Test(string value);
  Test(bool value);

};

If I create an object like this:

Test test("Just a test...");

The bool constructor is called!

Anyone knows why?

Thanks

Steve Guidi
  • 19,700
  • 9
  • 74
  • 90
user413185
  • 101
  • 3

6 Answers6

18

The type of "Just a test..." is const char *, which can be implicitly converted to either bool or std::string. Because std::string isn't a built in type, the const char *s is converted to a bool. You can prevent that by explicitly converting the const char * to a std::string:

Test test(std::string("Just a test..."));
Bill Carey
  • 1,395
  • 1
  • 11
  • 20
8

This is a well known C++ annoyance.

Your string literal has type of chat const[]. You've got two constructors, conversion sequences from char const[] to Test look like this:

1) char const[] -> char const* -> bool

2) char const[] -> char const* -> std::string

1) is a built-in standard conversion whereas 2) is a user-defined conversion. Built-in conversions have precedence over user defined conversions, thus your string literal gets converted more easily to bool than to std::string.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
4

The type of "Just a test..." is const char*. There is a built-in conversion from pointers to bool which is preferred over the non-built-in conversion from const char* to std::string.

The reason that the bool conversion is preferred is because std::string, while part of the standard library, is not a built-in type like integers, pointers, and booleans. It acts like any other class, and so its conversion constructors are considered only after conversions to built-in types.

Tyler McHenry
  • 74,820
  • 18
  • 121
  • 166
3

One way to circumvent this problem, is to provide another constructor taking a const char* and then converting explicitly to a std::string.

Milan
  • 3,342
  • 3
  • 31
  • 40
1

When you have a constructor (especially multiple constructors) that take only a single argument, it may be suitable to declare them "explicit" to avoid these kind of surprises. This forces the user of the class to make sure he gives the correct type to the constructor he wishes to use and prevents these implicit type conversions from being done behind the users back and hiding hard to find bugs.

http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=15&rll=1

In C++0x, this has been extended to conversion operators to prevent the same issue

http://www2.research.att.com/~bs/C++0xFAQ.html#explicit-convertion

David
  • 3,324
  • 2
  • 27
  • 31
0

One way is to create a variable of type std::string and pass the variable in:

std::string test = "TEST";
A a(test);

This way the type is explicitly defined as std::string it won't default to the constructor that accepts bool

Kenny Cason
  • 12,109
  • 11
  • 47
  • 72