Как вернуться к первой функции после вызова третьей функции - PullRequest
2 голосов
/ 26 ноября 2011

По сути, я хочу сделать следующее:

Из одной функции void A () я вызываю другую функцию void B ().B в свою очередь вызывает функцию void C ().Как я могу после некоторого утверждения вернуться к последней вызываемой строке в A из C?Если я набираю return, я возвращаюсь к B, но я не хочу, чтобы этот код в B выполнялся, если оператор в C истинен, я хочу оказаться в A. Я мог бы изменить C на bool C () и проверить этов Б, но я бы предпочел не.

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

Ответы [ 5 ]

2 голосов
/ 26 ноября 2011

что не так с этим?

void A() {
  B();
}

void B() {
  if (!C()) return;
  ...
}

bool C() {
  ..
}
2 голосов
/ 26 ноября 2011

Невозможно напрямую вернуться к чему-либо, кроме непосредственного вызова функции (в данном случае B), если вы не используете longjmp, что, я считаю, не рекомендуется в C ++.Однако если причина, по которой вы хотите пропустить B, состоит в том, что ошибка произошла в C, и ошибка может быть обработана только A, вы можете использовать исключения (предупреждение: неполный пример; мой C ++ становится ржавым):

#include <stdexcept>

void A() {
    try {
        B();
    }
    catch (std::exception& e) {
        // You'll get here if C throws
    }
}

void B() {
    C();
}

void C() {
    if (someCondition)
        return; // Sends you to B
    else
        throw std::exception; // Sends you to A since B does not contain a try/catch
}

Но, пожалуйста, не используйте исключения для регулярного (не исключительного) потока управления;используйте его только для фактических ошибок.

1 голос
/ 26 ноября 2011

Вы дали C неправильную подпись. Он должен быть bool C и возвращать индикатор «успеха» на B, который затем сразу возвращается на A или продолжается соответствующим образом.

0 голосов
/ 26 ноября 2011

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

jmp_buf env;

A()
{
  jmp_buf env;
  if ( !setjmp( &env ) )
  {
    B();
  }
  ...
}

B()
{
  C();
}

C()
{
  if ( for_some_reason )
  {
    longjmp( &env, 1 );
  }
}
0 голосов
/ 26 ноября 2011

Конечно, вы можете с помощью простого трюка:

leave
leave
ret

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

void C()
{
    printf("Inside C...\n");
    __asm__("leave");
    __asm__("leave");
    __asm__("ret");
}

void B()
{
    printf("Calling C...\n");
    C();
    printf("Returned from C...\n");
}

int main()
{
    B();
}

Вот вывод:

blackbear@blackbear-laptop:~$ ./a.out 
Calling C...
Inside C...
blackbear@blackbear-laptop:~$ 
...