Почему перегрузка функций-членов неявного преобразования работает по типу возвращаемого значения, в то время как это не разрешено для обычных функций?

C++ не допускает полиморфизма для методов на основе их возвращаемого типа. Однако при перегрузке функции-члена неявного преобразования это кажется возможным.

Кто-нибудь знает, почему? Я думал, что операторы обрабатываются как методы внутри.

Изменить: вот пример:

struct func {
    operator string() { return "1";}
    operator int() { return 2; }
};

int main( ) {
    int x    = func(); // calls int version
    string y = func(); // calls string version
    double d = func(); // calls int version
    cout << func() << endl; // calls int version
}

person grefab    schedule 14.07.2009    source источник
comment
Не могли бы вы привести пример? Я не уверен, что вы подразумеваете под перегрузкой по возвращаемому типу.   -  person mmx    schedule 15.07.2009
comment
Не могли бы вы привести пример?   -  person jkeys    schedule 15.07.2009


Ответы (4)


Операторы преобразования на самом деле не считаются разными перегрузками и не вызываются на основе типа возвращаемого значения. Компилятор будет использовать их только тогда, когда он должен (когда тип несовместим и должен быть преобразован) или когда его явно попросят использовать один из них с оператором приведения.

Семантически ваш код объявляет несколько разных операторов преобразования типов, а не перегрузки одного оператора.

person mmx    schedule 14.07.2009
comment
Операторы преобразования на самом деле не считаются разными перегрузками Они вообще не являются перегруженными функциями: у них разные имена. - person curiousguy; 05.12.2011

Это не возвращаемый тип. Это преобразование типов.

Учтите: func() создает объект типа func. Нет никакой двусмысленности относительно того, какой метод (конструктор) будет вызываться.

Остается только один вопрос: можно ли привести его к нужным типам. Вы предоставили компилятору соответствующее преобразование, так что он счастлив.

person EFraim    schedule 14.07.2009

На самом деле нет технической причины для предотвращения перегрузки функций для типов результатов. Это делается в некоторых языках, таких как, например, Ада, но в контексте C++, который также имеет неявные преобразования (и два их вида), полезность снижается, и взаимодействие обеих функций быстро приводит к неоднозначности.

Обратите внимание, что вы можете использовать тот факт, что неявные преобразования определяются пользователем, чтобы имитировать перегрузку по типу результата:

class CallFProxy;
CallFProxy f(int);

class CallFProxy {
   int myParameter;
   CallFProxy(int i) : myParameter(i) {}
public:
   operator double() { std::cout << "Calling f(int)->double\n"; return myParameter; }
   operator string() { std::cout << "Calling f(int)->string\n"; return "dummy"; }
};
person AProgrammer    schedule 15.07.2009
comment
На самом деле нет технической причины для предотвращения перегрузки функций по типам результатов. Ну, техническая причина заключается в том, что вызов функции имеет четко определенный тип в C++ (а не в Ada). Почти все выражения в C++ имеют четко определенный тип и значение, за исключением (1) бессмысленных подвыражений в вызове функции-члена в o.mf(), o.mf не является допустимым подвыражением и не имеет типа (если mf является членом функция, а не член данных); (2) адрес перегруженной функции, напр. &std::cos (cos(float), cos(double), ...?) - person curiousguy; 05.12.2011
comment
(...) В C++, чтобы определить значение выражения, вы можете начать с внутренних подвыражений, определить их значение и продолжить весь путь вверх (за исключениями, которые я только что упомянул). В Аде значение read() может зависеть от типа var в: var := read();. Обратите внимание, что read(); не является допустимым оператором: в Аде нет оператора-выражения. Вам нужно либо вызвать процедуру (не функцию!), либо выполнить присваивание. - person curiousguy; 05.12.2011

Разрешение перегрузки выбирает между несколькими функциями-кандидатами. В этом процессе возвращаемый тип кандидатов действительно не рассматривается. Однако в случае операторов преобразования «тип возвращаемого значения» имеет решающее значение для определения того, является ли этот оператор вообще кандидатом.

person MSalters    schedule 15.07.2009
comment
Эти функции-кандидаты имеют разные типы возврата, а также разные имена. Они не перегружены, еще меньше перегружены по возвращаемому типу. - person curiousguy; 05.12.2011
comment
@curiousguy: функции преобразования могут быть перегружены по cv-qualification и шаблонности. - person MSalters; 05.12.2011
comment
Это правильно, но в данном конкретном примере они не перегружены. - person curiousguy; 05.12.2011