How to access forward declaration in C++ class?

90 views Asked by At

The following code works, but it is not very readable to have methods separated from each state of this state machine:

struct Base {
    virtual Base* next() = 0;
};

struct StateA : public Base {
    Base* next();
};

struct StateB : public Base {
    Base* next();
};

StateA stateA;
StateB stateB;

Base* StateA::next() {
    return &stateB;
}

Base* StateB::next() {
    return &stateA;
}

I would rather prefer to have this structure, unfortunately, I don't know if it is possible in C++ to foward declare stateA and stateB:

struct Base {
    virtual Base* next() = 0;
};

struct StateA : public Base {
    Base* next() { return &stateB; }
};

struct StateB : public Base {
    Base* next() { return &stateA; }
};

StateA stateA;
StateB stateB;

Is it possible to keep the implementation of StateX along with their declaration?

I have tried to trick the compiler with this, but as guessed, it doesn't build:

struct Base {
    virtual Base* next() = 0;
};

struct StateA;
struct StateB;

extern StateA *stateAptr;
extern StateB *stateBptr;

struct StateA : public Base {
    Base* next() { return stateBptr; }
};

struct StateB : public Base {
    Base* next() { return stateAptr; }
};

StateA stateA;
StateB stateB;
StateA *stateAptr = &stateA;
StateB *stateBptr = &stateB;
1

There are 1 answers

0
273K On BEST ANSWER

The keyword extern is responsible for forward variable declarations. But it's can be used before their types are defined. You can split member function declarations and definitions.

struct Base {
    virtual Base* next() = 0;
};

struct StateA : public Base {
    Base* next();
};

struct StateB : public Base {
    Base* next();
};

StateB stateB;
StateA stateA;

Base* StateA::next() { return &stateB; }
Base* StateB::next() { return &stateA; }

Or update your trick for using Base* pointers.

struct Base {
    virtual Base* next() = 0;
};

extern Base *stateAptr;
extern Base *stateBptr;

struct StateA : public Base {
    Base* next() { return stateBptr; }
};

struct StateB : public Base {
    Base* next() { return stateAptr; }
};

StateA stateA;
StateB stateB;
Base *stateAptr = &stateA;
Base *stateBptr = &stateB;

But it does not improve readability in comparison with the first code, and conflicts with your sentence "it is not very readable".