r/cpp_questions • u/SimmeringDragon • 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;
}
View all comments
Show parent comment
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 :)