ggrr
ggrr

Reputation: 7867

Why do the print sequence of this code does not work as I expected?

I have a class System (ISystem as interface), which holds a Controller, either ControllerA or ControllerB. System can switch controller by calling 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;
        }
    }
};

In the main,I create a System and set it to state 0, then it should create ControllerA first, and then in ControllerA call stateChanged(1) to switch to ControllerB:

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

so I expect the output is:

state 0 with ControllerA
state 1 with ControllerB

but the result output sequence is :

state 1 with ControllerB
state 0 with ControllerA

why would that happen?

Upvotes: 0

Views: 53

Answers (3)

Simon Kraemer
Simon Kraemer

Reputation: 5680

You call to system.stateChanged(0); calls the constructor of ControllerA which calls system.stateChanged(1);.

The constructor of ControllerB does nothing and so you end up printing "state 1 with ControllerB\n" going back up into the first stateChanged call and print "state 0 with ControllerA\n"there.

Upvotes: 0

TartanLlama
TartanLlama

Reputation: 65600

You create the new ControllerA before outputting your message. Maybe you meant:

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

Although you should be using std::cout rather than printf in C++.

Upvotes: 0

Bartek Banachewicz
Bartek Banachewicz

Reputation: 39370

Because when you enter this:

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

It first calls the c-tor of A, which calls this:

system->stateChanged(1);

Which in turn does this:

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

Warning

But that essentially means that delete on the A object is called from inside of its constructor and that sounds kind of wrong. You might want to rethink this idea (starting with "raw pointers shouldn't ever own resources" guideline).

Upvotes: 2

Related Questions