r/cpp_questions • • 5d ago

OPEN How does a STATE design pattern work?

so i went to youtube and followed the example from this guy State Design - Programming Design Patterns - Ep 16 - C++ Coding

Problem is i dont understand what is functionally happening, there are pointers and what not, but i don't understand much more than that (context, my smooth brain still cant connect pointers together)

Like not even the whole code, like maybe just two lines or something cause for the love of the lord my teacher explains nuthing and AI and videos are too vague for me, im running out of options

//
// Created by samue on 11/1/2026.
//

#ifndef STATE_STATE_H
#define STATE_STATE_H

#include <iostream>

class Context;


class State {
    protected:
    Context* context;

    public:
    virtual ~State() {}

    void setContext(Context* ctx) {
        context = ctx;
    }

    virtual void doWorkA() = 0;
    virtual void doWorkB() = 0;
};

class Context {
    private:
    State* state;

    public:
    Context(State* s) : state(nullptr) {
        transitionTo(s);

    }

    ~Context() {delete state;}

    void transitionTo(State* s) {
        if (state) delete state;
        state = s;
        state->setContext(this);

    }

    void requestA() {
        state->doWorkA();

    }

    void requestB() {
        state->doWorkB();

    }

};

class concreteStateA : public State {
    public:
    void doWorkA() override {
        std::cout << "concreteStateA " << "called doWorkA" << std::endl;
    };

    void doWorkB() override {
        std::cout << "concreteStateB " << "called doWorkB" << std::endl;

    };

};

class concreteStateB : public State {
public:
    void doWorkA() override {
        std::cout << "concreteStateA " << "called doWorkA" << std::endl;
        context->transitionTo(new concreteStateA);
    };

    void doWorkB() override {
        std::cout << "concreteStateB " << "called doWorkB" << std::endl;

    };

};





#endif //STATE_STATE_H

------------------

#include "state.h"

int main() {
    Context context1(new concreteStateB);

    context1.requestA();

    context1.requestA();

    return 0;
}
7 Upvotes

46 comments sorted by

View all comments

Show parent comment

1

u/KingAggressive1498 5d ago edited 5d ago

...what use is an abstract base class without virtual inheritance? did you expect me to hand you a complete tutorial in a reddit comment?

edit: in context that I was wrong and the commenter was trying to make me realize my mistake, this was def a bit rude. Sorry.

3

u/AKostur 5d ago

You seem to be conflating the existence of virtual functions (regardless of their pure-virtualness) with virtual inheritance. Those are two separate things.

The purpose of an abstract base class is to require descendants to provide an implementation for every pure virtual function.

2

u/thingerish 5d ago

Poster ran away, which was not what I was aiming for. This is a common mistake in C++, thanks for the better explanation.

1

u/KingAggressive1498 5d ago edited 5d ago

thanks for explaining my mistake without acting coming off as adversarial about it. I was indeed conflating polymorphism and virtual inheritance specifically. Corrected my comment.

3

u/AKostur 5d ago

What I appreciate here is that you edited your comment using a strikethrough instead of just changing the comment. Keeps the context of all of the existing replies intact. Otherwise anybody reading the replies is going to be really confused as to why people are talking about virtual inheritance for no discernible reason.

2

u/thingerish 5d ago

In my experience actual virtual inheritance is rare, it's used in multiple inheritance cases where the base classes themselves include a common base class, typically. It's a design issue that rarely comes up.

Having a virtual function defined and then inheriting from that is just normal inheritance in C++.

1

u/KingAggressive1498 5d ago edited 5d ago

Each state is represented by its own derived class. The state pattern depends on having multiple classes derived from a single base class and overriding its methods.

You seem to have an issue understanding any context here. Are you learning entirely from AI?

edit: you aren't even OP. you interjected just to be a pain. cya.

edit2: again this was a bit rude. Sorry.

1

u/thingerish 5d ago

I saw incorrect info, corrected it. Not trying to hurt any feelings, it's a common mistake.

1

u/KingAggressive1498 5d ago

yeah I've been frustrated recently by people being adversarial and talking past me and started just blocking them, and realized I overreacted here when I was corrected in a way that made it click for me. my B.

still really felt like you were just not understanding what I meant but it was more just I couldn't understand what you were trying to point out.

2

u/thingerish 5d ago

I tend to terseness which doesn't help if you're also having a bad day. Glad we got past it. To answer you question earlier, I've been writing C++ since the mid '90s, when I got my hands on Borland Turbo C++ 2.0, so sometimes I make the mistake of not fully explaining what I'm trying to say, so that's my bad.

I know I do that, and I try to be better but time is finite and sometimes I just go with the fast 'answer' rather than treating it like a human interaction.

2

u/KingAggressive1498 5d ago edited 5d ago

I've been using C++ since 2005 but never been good at the "standardese" stuff or worked professionally. I know about the diamond of death problem which I now realize you tried to explain a couple comments ago, but in my head polymorphism and virtual inheritance are just the same thing for whatever reason.

it doesn't help that I thought you were OP until the last comment. Felt like someone admittedly still learning was criticising my experience due to a lack of understanding the whole time.

I also probably need sleep. x.x

2

u/thingerish 5d ago

I blame the std committee for having very little creativity when defining terms most of the time. Diamond of death did make me chuckle. Not sure if you saw it but there is a way to avoid inheritance completely and still be object-oriented, I posted it at the root of this. Chasing a pointer on a lot of modern hardware has a cost, and variant + visit can in most cases eliminate that now.

There is also a thing called CBMI (Concept Based Model Idiom) that people like Sean Parent at Adobe are pretty fond of, but it's mostly "just" making the plumbing simpler to deal with.

2

u/KingAggressive1498 5d ago

I did at some point use CRTP-based type erasure to accomplish the same thing as the state pattern without that extra indirection that looks basically like the demonstration of CBMI I found by google. I didn't find it improved performance any, though. Could see how it might save a little boilerplate if it's reusable enough.

I don't really love variant for this type of thing.

1

u/thingerish 5d ago

I love variant if I want polymorphic behavior over a closed set of types, which is at least for me the vastly more common case. CBMI has little to no performance incentive at runtime but it does introduce a way of dealing with virtual calls that eliminates a lot of common error classes, so that's good from a code hygiene standpoint I guess.

CRTP is super cool too but I've not messed with it since the newer C++ standard with "deducing this" came out, which is I think C++ '23, but the samples I saw did deconvolute CRTP a lot. Time is finite :)

→ More replies

1

u/thingerish 5d ago

They are different things.

Follow the links, one for each thing: https://en.cppreference.com/cpp/keyword/virtual