Как заставить функцию C ++ вернуться к своей первой строке? - PullRequest
0 голосов
/ 18 ноября 2010

Итак, у меня есть функция внутри консольного приложения win32 C ++, например:

void initFFmpeg(string url ,string container, int w, int h, int fps)
{// we want to return here

    encoder.SetConstants(fps, videoWidth, videoHeight, audioSampleRate);

    // ... more code...

    if (encoder.InitUrl(container, url, outputUserName) == -1)
    {
             // ...some more code...
             // Now we want to return
    } 
    // ... more code...
}

как включить такие возвраты?

Ответы [ 7 ]

6 голосов
/ 18 ноября 2010

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

Самый простой способ сделать то, что вы говорите, вы хотите с помощью goto:

void function()
{
top:
    // ...
    goto top;
    // ...
}

Редактировать: исправлено полностью фиктивно do..while пример.

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

void function()
{
    for (;;)
    {        
    // ...
        continue;
    // ...
        break;
    }
}
3 голосов
/ 18 ноября 2010

Похоже, что вы пытаетесь продолжать пробовать различные форматы, пока ffmpeg успешно не откроет URL.Это, вероятно, то, что вы хотите сделать (и имхо чище, чем использовать goto).

void initFFmpeg(string url ,string container, int w, int h, int fps)
{

    do {
        encoder.SetConstants(fps, videoWidth, videoHeight, audioSampleRate);

        // ... more code...

        // use whatever condition indicates success
        if (encoder.InitUrl(container, url, outputUserName) != -1)
            break;

        // ...some more code...

    } while (true) ;

    // ... more code...
}
2 голосов
/ 18 ноября 2010

Учитывая ваш код, ...

void initFFmpeg(string url ,string container, int w, int h, int fps)
{// we want to return here

    encoder.SetConstants(fps, videoWidth, videoHeight, audioSampleRate);

    // ... more code...

    if (encoder.InitUrl(container, url, outputUserName) == -1)
    {
             // ...some more code...
             // Now we want to return
    } 
    // ... more code here...
}

... и предполагая, что вы действительно хотите снова вызвать SetConstants, когда InitUrl не удастся, естественный способ выразить желаемое "возвращение""использовать оператор C ++ return, например ...

bool initEncoder(
    string const& url,
    string const& container,
    string const& userName
    )
{
    encoder.SetConstants( fps, videoWidth, videoHeight, audioSampleRate );

    // ... more code...

    if( encoder.InitUrl( container, url, userName ) == -1 )
    {
             // ...some more code...
             // Now we want to return, so:
             return false;
    } 
    return true;
}

void initFFmpeg( string const& url ,string const& container, int w, int h, int fps )
{
    while( !initEncoder( url, container, outputUserName ) )
    {}

    // ... more code here...
}

Вы также можете делать это с исключениями.Это может быть более понятно, но, вероятно, будет менее эффективным.Предполагая, что повторы являются общими.

Или, вы можете использовать continue в цикле for(;;).Мне не нравится continue, и он мало используется (по крайней мере, как сообщалось в Google Code Search несколько лет назад).Но это может быть только то, что доктор прописал в отношении убеждений коллег о том, что такое хороший код.

Примечание: технически также возможно использовать goto, но помимо использования в машинно-сгенерированном кодеэто лучше всего избегать.Для справки об этом см. Оригинальную статью Дейкстры 1968 года «Идти к вредным» .Хотя по состоянию на 2010 год ему 42 года, это все еще драгоценный камень - и лучше всего не забыт .

2 голосов
/ 18 ноября 2010

Это очень плохой стиль с ++, но может быть goto?

2 голосов
/ 18 ноября 2010

Вы можете использовать цикл while или цикл for для многократного перебора функции.Сколько раз это нужно назвать?Если всего два раза, вы, вероятно, можете просто вызвать функцию дважды, но более того, вы захотите использовать какой-то цикл.

Вы также можете использовать goto, но цикл, вероятно, лучше.

1 голос
/ 18 ноября 2010

Альтернативой зацикливанию или переходу является рекурсия.

void initFFmpeg(string url ,string container, int w, int h, int fps)
{
  encoder.SetConstants(fps, videoWidth, videoHeight, audioSampleRate);

  // ... more code...

  if (encoder.InitUrl(container, url, outputUserName) == -1)
  {
    initFFmpeg(url, container, w, h, fps);
    return;
  } 
  // ... more code...
}

Но рекурсия менее идиоматична в C ++, чем в некоторых других языках. Компиляторы C ++, как правило, не оптимизируют хвостовые вызовы, а глубокая рекурсия может затруднить отладку переполнения стека.

Я могу использовать рекурсию здесь, если я точно знаю, что она не может рекурсировать больше, чем несколько раз. В противном случае я бы, вероятно, просто использовал * дрожь * goto.

1 голос
/ 18 ноября 2010

Используйте цикл. Используйте форму do {} while, потому что вы, очевидно, хотите, чтобы все выполнялось хотя бы один раз.

void initFFmpeg(string url ,string container, int w, int h, int fps)
{
    bool success = false;
    do
    {
        encoder.SetConstants(fps, videoWidth, videoHeight, audioSampleRate);

        // ... more code...

        success = (encoder.InitUrl(container, url, outputUserName) != -1);
        if(!success)
        {
            // ... more code ...
        }

        // ... more code ...

    } while(!success);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...