0

I have two overloaded constructors:

Hello::Hello(std::string message)
{
}

Hello::Hello(int *number)
{
}

Either of those constructors can take a memory address. If I did Hello hi(NULL); then which would be called?

Also if you could explain the rules as they concern objects that are overloaded. Like similarly if I had one constructor that took a long for a parameter (Object::Object(long x)) and another overload (Object::Object(SomeOtherObject o)) that takes an object which itself had an overload for a long (SomeOtherObject::SomeOtherObject(long x)). Then I call Object obj((long)5); is it guaranteed to call one or the other?

pmr
  • 58,701
  • 10
  • 113
  • 156
loop
  • 3,460
  • 5
  • 34
  • 57

3 Answers3

2

Caling the std::string constructor would require an extra implicit conversion, so int* is preferred.

For the second scenario, then the initial constructor is preferred. Why would the compiler look for any of the other constructors when it has a perfect match right there? And again, it includes an implicit conversion, which is worse than the perfect match the direct long constructor provides.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • I'm marking this as correct. It's pretty much the same as pmr's answer but yours is more expanded on the second scenario. If you can please consider quoting the part of the C++ standard that covers your reply. – loop Aug 13 '12 at 02:01
  • @test The standard has tons to say about overload resolution and quoting isn't of much use. For a beginner it is often enough to understand that it will do what is most intuitive and what requires the least amount of conversion and that a exact match of types will also be preferred. To fully understand the topic you need to know a lot about implicit built-in conversions and user defined conversions. That would be a huge quote. – pmr Aug 13 '12 at 07:51
  • 1
    An extra _implicit_ conversion? IIRC, that's impossible (a conversion sequence contains at most one), and furthermore `std::string::string(const char*)` is counted as a user-defined conversion even though it's from `std::`. – MSalters Aug 13 '12 at 08:39
  • Pretty sure that "extra" going from 0 to 1 would be one extra. – Puppy Aug 13 '12 at 10:38
2

That there is a constructor is completely irrelevant to your example. It is simply about overload resolution and you can check it with two functions:

void foo(std::string s) {
}

void foo(int* n) {
}

Calling foo(NULL) will result in calling foo(int*). NULL is the null-pointer constant and can be implicitly converted to every pointer type and the best conversion in this context is to int*. The other overload would require two conversions, which is rated worse.

The second scenario is pretty obvious: The perfect match is preferred.

pmr
  • 58,701
  • 10
  • 113
  • 156
1

W.r.t. the issue you point out in your second question, overload resolution can be forced to behave in an expected manner.

When you have a class constructor with a single object, like your Object(SomeOtherObject o), style-wise is better to mark that constructor with the word explicit, so the compiler will not try to make implicit conversions. E.g. given the definitions:

class A {
  A(int x);
};

class B {
  explicit B(A a);
};

trying to create an object like B b(100) would be a compile error.

See also the Google C++ Style Guide section on this topic.

Marco Leogrande
  • 8,050
  • 4
  • 30
  • 48