Возвращаемый тип полиморфизма в C-подобных языках - PullRequest
11 голосов
/ 30 октября 2008

Почему мы не видим C-подобные языки, которые допускают вызовы с полиморфизмом в возвращаемом типе? Я мог видеть, как дополнительный вывод типа был бы препятствием, но у нас есть множество языков с полноценными системами вывода типов (которые работают для различных уровней "работы").

Редактировать: Под полиморфизмом возвращаемого типа я подразумеваю перегрузку сигнатуры функции только в возвращаемом типе. Например, C ++ и Java допускают перегрузку только в типе формальных параметров, но не в типе возврата.

Ответы [ 5 ]

16 голосов
/ 30 октября 2008

Если под «полиморфизмом возвращаемого типа» вы подразумеваете перегрузку, основанную на типе возвращаемого значения, я не уверен насчет других языков, но для C ++ вот ответ (в значительной степени из уст лошади):

Типы возвращаемых функций не вступают в игру в разрешении перегрузки просто потому, что Страуструп (я полагаю, с помощью других архитекторов C ++) хотел, чтобы разрешение перегрузки было «независимым от контекста». См. 7.4.1 - «Перегрузка и тип возврата» в «Языке программирования C ++, третье издание».

Причина в том, чтобы сохранить разрешение для отдельный оператор или функция вызов контекстно-независимый.

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

И, Господь знает, разрешение перегрузки в C ++ достаточно сложное ...

4 голосов
/ 30 октября 2008

Я хотел бы видеть эту функцию на каком-то языке, не только для того, чтобы функция foo могла возвращать double или int или строку, но также чтобы foo могла возвращать структуру или объекты разных классов. Устранение неоднозначности вызовов будет довольно тривиальным - если вызов неоднозначен, потребуется приведение типа для выбора желаемого типа возврата. Пример:

string s = foo();    //foo returns a string
double x = foo();    //foo returns a double
int i = foo();       //foo returns an integer
float f = (float)(int)foo();    //call the int foo and convert to float

дополнительно

Animal a = fooFactory();    //fooFactory returns an Animal
Plant p = fooFactory();     //foofactory returns a Plant

эти ситуации возникают не очень часто, но когда они делают, обходной путь часто бывает довольно уродливым ...

3 голосов
/ 30 октября 2008
double x = (double)foo();

Вышеуказанное неоднозначно, если есть версии foo (), которые могут возвращать double, int, float и т. Д.

2 голосов
/ 30 октября 2008

В C ++ вы можете сделать это с классами в значительной степени. Например, скажем, у меня есть тип данных, который обычно преобразуется в ASCII при вводе и выводе;

typedef char* pchar;

class   MyType
{
public:

 operator pchar() { return(ConvertToASCII()); }
 MyType& operator=(char* input) { ConvertFromASCII(input); return(*this); }

 pchar ConvertToASCII();
 void ConvertFromASCII(pchar ASCII);
}

Этот тип вещей часто используется в платформах C ++. Например, взгляните на реализацию класса Mtc CString. ИМХО, это очень полезный инструмент, хотя и опасный при определенных обстоятельствах.

0 голосов
/ 30 октября 2008

Из-за автоматического преобразования типов не очевидно, какую функцию вызывать, когда возвращаемые типы близки.

...