【问题标题】:How to handle and avoid Recursions如何处理和避免递归
【发布时间】:2015-05-20 16:16:57
【问题描述】:

我正在使用自定义类来管理自动售货机。我不知道为什么它一直抛出堆栈溢出错误。我的程序有两个版本,第一个是通过预定义某些变量来查看类等是否工作的基本测试。第二个版本应该是这样的,每次运行程序时,有问题的变量都会发生变化(取决于用户输入)。

如果有人能提出避免这种递归或堆栈溢出的方法,我会很好。下面是涉及的三个类的代码;

class Filling
{
protected:
    vector<Filling*> selection;
    string fillingChosen;

public:
    virtual float cost()
    {
        return 0;
    }
    virtual ~Filling(void)
    {
        //needs to be virtual in order to ensure Condiment destructor is called via Beverage pointer
    }
};

class CondimentDecorator : public Filling
{
public:
    Filling* filling;
    void addToPancake(Filling* customerFilling)
    {
        filling = customerFilling;
    }

    ~CondimentDecorator(void)
    {
        delete filling;
    }

};


class Frosted : public CondimentDecorator
{
    float cost()
    {       //ERROR IS HERE//
        return (.3 + filling->cost());
    }
};

下面是调用上述'cost'函数的代码;

void displayCost(Filling* selectedFilling)
{
    cout << selectedFilling->cost() << endl;
}

下面是启动它的部分代码(main方法);

Filling* currentPancake = NULL;
            bool invalid = true;
            do
            {
                int selection = makeSelectionScreen(money, currentStock, thisState);
                invalid = false;

                if (selection == 1)
                {
                    currentPancake = new ChocolateFilling;
                }
                else if...

.
.
.
.
                else
                    invalid = true;


            } while (invalid);

            bool makingSelection = true;
            CondimentDecorator* currentCondiment = NULL;
                do
                {
                    int coatingSelection = makeCoatingSelectionScreen(money, currentStock, thisState);

                    if (coatingSelection == 1)
                        currentCondiment = new Frosted;
                    else if (coatingSelection == 2)...
.
.
.
                    else if (coatingSelection == 0)
                        makingSelection = false;

                    currentCondiment = thisSelection;
                    currentCondiment->addToPancake(currentPancake);
                    currentPancake = currentCondiment;
                    displayCost(currentPancake);



//Below is the code that DOES work, however it is merely meant to be a test. The 
//above code is what is needed to work, however keeps causing stack overflows
//and I'm uncertain as to why one version works fine and the other doesn't

                    /*currentCondiment = new Frosted;
                    currentCondiment->addToPancake(currentPancake);
                    currentPancake = currentCondiment;
                    displayCost(currentPancake);

                    currentCondiment = new Wildlicious;
                    currentCondiment->addToPancake(currentPancake);
                    currentPancake = currentCondiment;
                    displayCost(currentPancake);*/


                } while (makingSelection);

                displayCost(currentPancake);


                delete currentPancake;

【问题讨论】:

  • 在调试器下运行你的程序,当你得到堆栈溢出时检查堆栈的状态,你应该立即明白什么方法递归失控了。
  • @MatteoItalia 这是Frosted::cost
  • @MatteoItalia 我知道哪个方法是递归的,我只是不知道如何解决它,因为我以前从未遇到过这个错误;)

标签: c++ recursion stack-overflow


【解决方案1】:

当您使用Frosted 调用displayCost 时发生无限递归,而filling 也是Frosted。这就是发生在这里:

currentCondiment->addToPancake(currentPancake);
currentPancake = currentCondiment;
displayCost(currentPancake);

您将currentCondimentfilling 设置为currentPancake,然后使用currentCondiment 调用displayCost


在此过程中,您还泄漏了最初分配给currentPancake 的内存。

顺便说一句,currentCondiment = thisSelection; 也会泄漏内存。

想法:使用像std::unique_ptr 这样的智能指针来消除泄漏。

【讨论】:

  • 感谢您的帮助:)
  • 对不起,我昨天忘了说我找到了解决问题的替代方法。我不得不把`currentCondiment->addToPancake(currentPancake);`和`currentPancake = currentCondiment;`放到一个if语句中,因为如果我选择了0(退出菜单/确认选项),它就会继续运行最后一个'currentCondiment'或类似的东西。无论哪种方式,将它放在 if 语句中都可以修复它。我还恢复到以前没有使用currentCondiment = thisSelection 的版本。我现在也删除了currentCondiment,不确定这是否能修复泄漏?
猜你喜欢
  • 2021-05-13
  • 2013-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多