'Destructors but for functions

New to c++ and possibly a really stupid question, but is there something like a destructor but for functions? I making a sort of game and as you can see that the way I made this program is that theres a bunch of functions, and then for switch cases that watches for your choices. Picking a switch case causes you to go to another function, and then that functions will lead you to calling another function. I know this is pretty stupid and is probably the reason why my game crashes. I was just wondering if there is an equivalent to a destructor but for classes. If not, what would be a better way to implement something like this, where after doing one event, you go back to choosing another event?

void wizard::enterFloorTwo(){
    a.outputLine("wizard.txt", 48);
    a.outputLine("wizard.txt", 1);
    a.outputLine("wizard.txt", 50);
    a.outputLine("wizard.txt", 51);
    a.outputLine("menu.txt", 13);
    if(secFloorProgress > 0){
        a.outputLine("wizard.txt", 52);
    }
    a.outputLine("wizard.txt", 1);
    while (condition == 0) {
    cin >> userInput;
        switch (userInput) {
            case 1: {
                if(portalDone == false){
                    secFloorProgress++;
                    portalDone = true;
                    tamperPortal();
                }
                else{
                    cout << "This activity has already been done." << endl;
                    break;
                }
            }
            case 2: {
                if(dragonDone == false){
                    secFloorProgress++;
                    dragonDone = true;
                    freeDragon();
                }
                else{
                    cout << "This activity has already been done." << endl;
                    break;
                }
            }
            case 3: {
                string name =  ply.getName();
                int attack = ply.getAtk();
                int defense = ply.getDef();
                int health = ply.getHealth();
                int plague = ply.getPlague();
                int money = ply.getMoney();
                hubMenu(2);
                system("pause");
            }
            case 4: {
                if(secFloorProgress > 0){
                    a.outputLine("wizard.txt", 98);
                    enterWizardBoss();
                    a.outputLine("wizard.txt", 1);
                }
                else{
                    cout << "That is not a valid option." << endl;
                    break;
                }
            }
            default: {
                cout << "That is not a valid option." << endl;
            }
        }
    }
}

void wizard::tamperPortal(){
    a.outputLine("wizard.txt", 56);
    a.outputLine("wizard.txt", 1);
    a.outputLine("wizard.txt", 58);
    pickLock();
}

void wizard::pickLock(){
    bool repeat = true;
    while(repeat == true){
        a.outputLine("wizard.txt", 22);
        bool val = randGameHard();
        if (val == true) {
            repeat = false;
            a.outputLine("wizard.txt", 72);
            a.outputLine("wizard.txt", 73);
            while (condition == 0) {
                cin >> userInput;
                switch (userInput) {
                    case 1: {
                        a.outputLine("wizard.txt", 79);
                        a.outputLine("wizard.txt", 1);
                        a.outputLine("wizard.txt", 80);
                        system("pause");
                        secFloorProgress++;
                        enterFloorTwo();
                        break;
                    }
                    case 2: {
                        a.outputLine("wizard.txt", 83);
                        a.outputLine("wizard.txt", 1);
                        a.outputLine("wizard.txt", 84);
                        system("pause");
                        secFloorProgress++;
                        enterFloorTwo();
                        break;
                    }
                    case 3: {
                        a.outputLine("wizard.txt", 87);
                        system("pause");
                        secFloorProgress++;
                        enterFloorTwo();
                        break;
                    }
                    default: {
                        cout << "That is not a valid option." << endl;
                    }
                }
            }
        }   
        else {
            if(lockpick > 1){
                a.outputLine("wizard.txt", 62);
                lockpick--;
                cout << "You only got " << lockpick <<" more picks left." << endl;
                bool chance =  randChance();
                if (chance == true) {
                    a.outputLine("wizard.txt", 1);
                    //wc.engage(wp, we2);
                    system("pause");
                }
                else{
                    a.outputLine("wizard.txt", 1);
                }
            }
            else{
                a.outputLine("wizard.txt", 70);
                enterFloorTwo();
            }
        }
    }
}

void wizard::freeDragon(){
    a.outputLine("wizard.txt", 91);
    system("pause");
    bool chance =  randChance();
    if (chance == true) {
        a.outputLine("wizard.txt", 1);
        //wc.engage(wp, we2);
        system("pause");
    }
    else{
        a.outputLine("wizard.txt", 1);
    }
    a.outputLine("wizard.txt", 94);
    enterFloorTwo();
}


Solution 1:[1]

If I understand you right the problem you are seeing is that every function will call another and another and another and never return. SO after a bunch of moves the stack overflows and the game crashes.

Well, first this shouldn't happen with a decent compiler if those function calls are all tail calls. This can be a perfectly valid way to implement a game. But it might be a bit fragile. The compiler is not forced to make tail calls or you can write code that isn't a tail call by accident.

So there are some ways around it.

First you could have a global state variable that says which function to call next. Then in the places where you call for example tamperPortal() you only set the global state variable to tamperPortal and return. The main game loop when checks the global state variable and calls the function. So each game move starts fresh on the stack. Look up state machines for this.

Note: the state variable can be an enum or a function pointer.

A different solution is to return the function pointer instead of a global state. Again the idea is to make the function end and unroll the stack before calling the function for the next move.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Goswin von Brederlow