Как вернуться к первой функции после вызова третьей функции

В принципе, я хочу сделать следующее:

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

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


person pigelin    schedule 26.11.2011    source источник
comment
Почти наверняка вы пытаетесь сделать что-то, что можно сделать лучше, если подумать. Почему бы не описать реальную проблему, которую вы пытаетесь решить?   -  person Kerrek SB    schedule 26.11.2011
comment
Ok. Я делаю небольшую текстовую игру. Таким образом, функция A — это, по сути, то, что я называю action(), где персонаж, в свою очередь, делает свой ход. Из action() я могу вызвать бой(), если хочу сразиться с другим персонажем. бой() пошаговый, поэтому для каждого хода персонажа в бою вы вызываете hit(). В hit() я хочу добавить выбор ввода для бега вместо боя. Когда я бегу, я хочу выйти из боя(), но не из действия().   -  person pigelin    schedule 26.11.2011


Ответы (5)


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

void A() {
  B();
}

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

bool C() {
  ..
}
person perreal    schedule 26.11.2011
comment
Я закончил с этим. Спасибо. - person pigelin; 26.11.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
}

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

person Aasmund Eldhuset    schedule 26.11.2011

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

person dmckee --- ex-moderator kitten    schedule 26.11.2011
comment
Это то, о чем я тоже думал. Просто хотел избежать этого, потому что тогда мне придется изменить много кода. - person pigelin; 26.11.2011

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

jmp_buf env;

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

B()
{
  C();
}

C()
{
  if ( for_some_reason )
  {
    longjmp( &env, 1 );
  }
}
person AndersK    schedule 26.11.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:~$ 
person BlackBear    schedule 26.11.2011
comment
@pezcode: ах, я неправильно понял твой комментарий. Что ж, я не думаю, что то, что спрашивает ОП, является стандартным C, поэтому это наверняка будет зависеть от чего-то. Это a решение, лучшее, что я могу придумать :) - person BlackBear; 26.11.2011