C ++ - Перегрузка конструктора - приватная и публичная - PullRequest
8 голосов
/ 13 марта 2009

Можете ли вы сказать мне, почему следующий код дает мне следующую ошибку - вызов перегруженного "C (int)" является неоднозначным

Я бы подумал, что, поскольку C (char x) является приватным, снаружи виден только ctor C (float), и это следует вызывать путем преобразования int в float.

Но это не тот случай.

class C
{
    C(char  x)
    {
    }
public:
    C(float t)
    {
    }
};

int main()
{
    C p(0);
}

Ответы [ 3 ]

18 голосов
/ 13 марта 2009

Это обсуждается в "Эффективном C ++" Скоттом Мейером. Причина этого двусмысленна в том, что они хотели убедиться, что простое изменение видимости члена не изменит значения уже существующего кода в другом месте.

В противном случае, предположим, что ваш класс C был где-то в заголовке. Если у вас есть частный член C (int), код, который вы предоставляете, будет называться C (float). Если по какой-то причине член C (int) был открыт, старый код неожиданно вызвал бы этот член, даже если ни старый код , ни вызываемая им функция не изменились .

РЕДАКТИРОВАТЬ: Больше причин:

Еще хуже, предположим, что у вас были следующие 2 функции:

C A::foo() 
{
    return C(1.0);
}

C B::bar() 
{
    return C(1.0);
}

Эти две функции могут вызывать разные функции в зависимости от того, был ли foo или bar объявлен другом C, или A или B наследуется от него. Наличие идентичного кода для вызова различных функций пугает.

(Вероятно, это не так хорошо, как обсуждение Скотта Мейера, но это идея.)

7 голосов
/ 13 марта 2009

0 - это тип int. Поскольку он может быть неявно приведен либо к float, либо к char в равной степени, вызов неоднозначен. Видимость не имеет значения для этих целей.

Либо поместите 0.0, 0. или 0.0f, либо полностью избавьтесь от конструктора C(char).

Редактировать: Соответствующая часть стандарта, раздел 13.3:

3) [...] Но как только функции-кандидаты и списки аргументов были определены, выбор наилучшей функции остается одинаковым во всех случаях:

  • Во-первых, подмножество функций-кандидатов - те, которые имеют надлежащее количество аргументов и удовлетворяют некоторым другим условиям - выбирается для формирования набора жизнеспособных функций (13.3.2).
  • Затем выбирается наилучшая жизнеспособная функция на основе последовательностей неявного преобразования (13.3.3.1), необходимых для сопоставления каждого аргумента с соответствующим параметром каждой жизнеспособной функции.

4) Если наилучшая жизнеспособная функция существует и является уникальной, разрешение перегрузки успешно выполняется и в результате выдает ее. В противном случае разрешение перегрузки завершится неудачно, и вызов будет некорректным. Когда разрешение перегрузки завершается успешно, и наилучшая жизнеспособная функция недоступна (пункт 11) в контексте, в котором она используется, программа плохо сформирована.

Обратите внимание, что видимость не является частью процесса выбора.

0 голосов
/ 13 марта 2009

Не думаю, что:

C p(0);

преобразуется в:

C(float t)

Вам, вероятно, нужно сделать:

C p(0.0f);
...