开发者

How to make C++ function return to its first line?

So I have a function inside a win32 C++ console application like:

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...开发者_如何学编程
}

how to enable such returns?


Usually there's an natural loop that you can express (while, for or do...while), otherwise it feels like poor design to want to arbitrarily jump to the top of a function.

The easiest way to do what you say you want is with a goto:

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

Edit: fixed totally bogus do..while example.

Some people don't like the word goto and will insist on wrapping everything in a forever loop and using continue, but it's just a goto by another name.

void function()
{
    for (;;)
    {        
    // ...
        continue;
    // ...
        break;
    }
}


It appears that what you're trying to do is to keep trying various formats until ffmpeg successully opens the url. This is probably what you want to do (and IMHO cleaner than using a 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...
}


You can use a while loop or a for loop to iterate over the function multiple times. How many times should it be called? If just twice, you can probably just call the function twice, but for more than that you'll want to use a loop of some sort.

You could also use a goto, but a loop is probably better.


It is very bad c++ style but maybe goto ?


Given your code, ...

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...
}

... and assuming that you really do want to call SetConstants again when InitUrl fails, a natural way to express your desired "return" is to use the C++ return statement, like ...

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...
}

You can also do it with exceptions. That might be more clear but it'll probably be less efficient. Assuming that retries are common.

Or, you can use a continue in a for(;;) loop. I don't like continue, and it's not much used (at least as reported by Google Code Search a few years ago). But it might be just what the doctor ordered with respect to co-workers' beliefs about what's good code.

Note: it's technically also possible to use a goto, but apart from use in machine-generated code those are best avoided. For background on that, see Dijkstra's original 1968 article "Go to considered harmful". Although as of 2010 it's 42 years old, it's still a gem -- and best not forgotten.


Use a loop. Use the do{ }while form because you obviously want everything to execute at least once.

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);
}


An alternative to looping or goto is recursion.

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...
}

But recursion is less idiomatic in C++ than in some other languages. C++ compilers tend not to optimize tail calls and deep recursion can cause hard to debug stack overflows.

I may use recursion here if I knew for sure that it can't recurse more than a few times. Otherwise I would probably just use a *shiver* goto.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜