2014-11-26 4 views
5

Пусть класс существует следующим образом:Возвращение из пустоты функции

class Foo 
{ 
    void do_after_something() 
    { 
    //some code here 
    return; 
    } 

    void do_something() 
    { 
    //some code here 
    return do_after_something(); //returning another (void) function 
    } 
}; 

JAVA явно против чего-то вроде выше, компилятор Borland C++ выдает предупреждение, MS VC++ не жалуется.

Мой вопрос: должен ли логический (теоретический) возврат из функции пустоты?

return do_after_something(); 

в противоположность:

do_after_something(); 
return; 

или это все реализации (компилятор/язык) зависит?

+0

Это имеет смысл, но не в Java или C++, для которых возвращаемый void обозначается возвратом без аргумента. Во всяком случае, вы часто видите функцию возврата void как процедуру, то есть часть кода с побочным эффектом, а не функцию, которая вычисляет ... нет значения. –

+5

Ну да, это все зависит от языка. Вы легко можете представить себе язык под названием Vava, который является таким же, как Java, за исключением этого. –

+0

Имейте в виду, что оба этих языка эволюционировали из C, изначально не имевшего 'void'. Все функции были определены для возврата чего-либо ('int' по умолчанию), и вы можете назначить переменную для результата функции, которая никогда не возвращала значения, давая вам мусор. С другой стороны, в Algol/Pascal/Ada вы пишете либо 'procedure' (который не возвращает значение), либо' function' (что делает). Вы могли бы сказать, что функция 'void' является попыткой добавить' procedure' в C, чтобы предотвратить использование результатов мусора функций, которые ничего не возвращают. – ajb

ответ

8

Философски, вы могли утверждать, что возвращение результат void -returning функции должны быть разрешены, но, к сожалению, это не тот случай, по крайней мере, для Java.

Это является действительным для C++ однако. Если вы попробуете следующую программу:

#include <iostream> 

void xyzzy(void) {} 
void plugh(void) { return xyzzy();} 

int main() { 
    std::cout << "Hello\n"; 
    plugh(); 
    return 0; 
} 

будет работать нормально.

Это подробно описан в ISO C++11 6.6.3 /3:

Ответное заявление с выражением типа void может использоваться только в функциях с типом возвращаемого cv void; выражение вычисляется непосредственно перед возвратом функции к вызывающему.

Так что это действительно равноценны утверждать, что путь Java является правильным, если вы думаете о void как не фактического типа, а как отсутствие чего-то. Например, если у вас есть:

int xyzzy(void) { return 42; } 

в C, вы не обязаны указать аргумент правильно (не) типа, например, с:

void plugh; 
int twisty = xyzzy(plugh); 

Дитто, С ++ путь правильный, но по-другому - языки - это то, что они есть.

+1

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

1

В C++ 11 его возможные и законные. Вы можете вернуть функцию void из другой функции void. Refrence Язык программирования C++ Глава 12, Bjarne Strousstrup

2

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

Это не считается полезным для этого в C (хотя я думаю, что это может быть разрешено), потому что нет необходимости в нем.В любое время вы делаете:

return someVoidFn(); 

Вы всегда можете перевести, что:

someVoidFn(); 
return; 

И получить тот же эффект.

Однако, на C++ и Java, возврат функции void имеет реальное использование, и это потому, что эти языки имеют шаблоны и генерические файлы. Рассмотрим это (не очень полезно) Java класс:

class NestedIdentity<T> { 
    T run(int i, T value) { 
    if (i == 0) return value; 
    return run(i - 1); 
    } 
} 

Его run метод возвращает значение, которое вы пройти к нему, после того, называющая себя заданное число раз. Я знаю, бессмысленно, правда? Но важная часть состоит в том, что Tможет быть недействительным. Вы можете сделать это:

NestedIdentity<Void> nest = new NestedIdentity<Void>(); 
nest(5, null); 

И это работает. В Java Void (обратите внимание на капитализацию) создает экземпляр общего типа с типом void, единственным значением которого является null. Если Java не разрешало возвращать выражение void в методе void, это должно было быть ошибкой времени компиляции для создания экземпляра generic с помощью void.