Разрешение перегрузки при вызове с NULL в качестве аргумента
У меня есть два перегруженных конструктора:
Hello::Hello(std::string message)
{
}
Hello::Hello(int *number)
{
}
Любой из этих конструкторов может занять адрес памяти. Если бы я сделал Hello hi(NULL);
тогда что будет называться?
Также, если вы могли бы объяснить правила, поскольку они касаются перегруженных объектов. Аналогично, если бы у меня был один конструктор, который долго занимал параметр (Object::Object(long x)
) и еще одна перегрузка (Object::Object(SomeOtherObject o)
), который принимает объект, который долгое время имел перегрузку (SomeOtherObject::SomeOtherObject(long x)
). Тогда я звоню Object obj((long)5);
гарантированно позвонить одному или другому?
3 ответа
Caling std::string
конструктор потребует дополнительного неявного преобразования, поэтому int*
является предпочтительным.
Для второго сценария предпочтительным является исходный конструктор. Зачем компилятору искать какой-либо из других конструкторов, когда он имеет идеальное совпадение? И опять же, он включает в себя неявное преобразование, которое хуже, чем идеальное совпадение с прямым long
конструктор предоставляет.
То, что есть конструктор, совершенно не имеет отношения к вашему примеру. Это просто разрешение перегрузки, и вы можете проверить это с помощью двух функций:
void foo(std::string s) {
}
void foo(int* n) {
}
призвание foo(NULL)
приведет к звонку foo(int*)
, NULL
является константой нулевого указателя и может быть неявно преобразована в каждый тип указателя, и наилучшим преобразованием в этом контексте является int*
, Другая перегрузка потребует двух преобразований, что оценивается хуже.
Второй сценарий довольно очевиден: идеальное совпадение предпочтительнее.
В связи с проблемой, на которую вы указали в своем втором вопросе, разрешение перегрузки можно заставить вести себя ожидаемым образом.
Когда у вас есть конструктор класса с одним объектом, как ваш Object(SomeOtherObject o)
по стилю лучше пометить этот конструктор словом explicit
, поэтому компилятор не будет пытаться делать неявные преобразования. Например, учитывая определения:
class A {
A(int x);
};
class B {
explicit B(A a);
};
пытаясь создать объект, как B b(100)
будет ошибка компиляции.
См. Также раздел " Руководство по стилю Google C++" по этой теме.