Почему перегрузка функций-членов неявного преобразования работает по типу возвращаемого значения, хотя для обычных функций это не разрешено?
-
13-09-2019 - |
Вопрос
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
}
Решение
Операторы преобразования на самом деле не считаются разными перегрузками и не вызываются на основе их тип возвращаемого значения.Компилятор будет использовать их только тогда, когда должен (когда тип несовместим и должен быть преобразован) или когда явно предложено использовать один из них с оператором приведения.
Семантически ваш код объявляет несколько другой операторы преобразования типов и не перегрузки одного оператора.
Другие советы
Это не возвращаемый тип.Это преобразование типов.
Учитывать:func() создает объект типа func.Нет никакой двусмысленности относительно того, какой метод (конструктор) будет вызван.
Остается единственный вопрос: можно ли привести его к нужным типам.Вы предоставили компилятору соответствующее преобразование, и он доволен.
На самом деле нет технической причины предотвращать перегрузку функций для типов результатов.Это делается, например, в некоторых языках, таких как Ada, но в контексте 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"; }
};
Разрешение перегрузки выбирает между несколькими функциями-кандидатами.В этом процессе возвращаемый тип кандидатов действительно не учитывается.Однако в случае операторов преобразования «тип возвращаемого значения» критически важен для определения того, является ли этот оператор вообще кандидатом.