为什么这段代码的打印顺序不能像我预期的那样工作?

时间:2015-10-09 09:59:50

标签: c++

我有一个类System(ISystem as interface),它包含一个Controller,ControllerA或ControllerB。系统可以通过调用stateChanged:

来切换控制器
#include <stdio.h>
class ISystem{
public:
    virtual void stateChanged(int state)=0;
};

class Controller{};

class ControllerA : public Controller{
public:
    ControllerA(ISystem* system){
        system->stateChanged(1);
    }
};

class ControllerB : public Controller{
public:
    ControllerB(ISystem* system){}
};

class System : public ISystem{
protected:
    Controller* controller;
public:
    System(){this->controller=NULL;}
    void stateChanged(int state){
        if(controller!=NULL){
            delete controller;
        }
        switch(state){
            case 0:
            controller=new ControllerA(this);
            printf("state 0 with ControllerA\n");
            break;
            case 1:
            controller=new ControllerB(this);
            printf("state 1 with ControllerB\n");
            break;
        }
    }
};

在main中,我创建一个System并将其设置为状态0,然后它应该首先创建ControllerA,然后在ControllerA中调用stateChanged(1)以切换到ControllerB:

int main(){
    System system;
    system.stateChanged(0);
    return 0;
}

所以我希望输出是:

state 0 with ControllerA
state 1 with ControllerB

但结果输出序列是:

state 1 with ControllerB
state 0 with ControllerA

为什么会发生这种情况?

3 个答案:

答案 0 :(得分:2)

因为当你输入这个:

case 0:
controller=new ControllerA(this);
printf("state 0 with ControllerA\n");
break;

首先调用A的c-tor,调用它:

system->stateChanged(1);

反过来这样做:

case 1:
controller=new ControllerB(this);
printf("state 1 with ControllerB\n");
break;

警告

但这实际上意味着delete对象上的A从其构造函数中被称为,这听起来有点不对。您可能想重新考虑这个想法(从“原始指针不应该拥有资源”指南开始)。

答案 1 :(得分:0)

您在输出消息之前创建新的ControllerA。也许你的意思是:

void stateChanged(int state){
    if(controller!=NULL){
        delete controller;
    }
    switch(state){
        case 0:
        printf("state 0 with ControllerA\n"); //print before creating
        controller=new ControllerA(this);
        break;
        case 1:
        printf("state 1 with ControllerB\n"); //ditto
        controller=new ControllerB(this);
        break;
    }
}

虽然你应该在C ++中使用std::cout而不是printf

答案 2 :(得分:0)

您致电system.stateChanged(0);调用ControllerA的构造函数,该构造函数调用system.stateChanged(1);

ControllerB的构造函数不执行任何操作,因此您最终打印"state 1 with ControllerB\n"返回到第一个stateChanged调用并在那里打印"state 0 with ControllerA\n"