class Car { class BaseState { explicit BaseState(Car* vehicle) : mVehicle(vehicle) {} virtual void run() = 0; Car* mVehicle; } class State1 : public BaseState { explicit State1(Car* vehicle) : BaseState(vehicle) {} virtual void run() {
All states are made from BaseState, so they have an mVehicle member variable to access external class variables. However, in each derived class in all functions of each state, static_cast is required to access the variables and functions of members of the derived class.
The best solution?
- In each state of derived classes, add another pointer (for example, Convertible * mConvertible). Each state has double pointers (mConvertible and mVehicle) pointing to the same object. Doesn't look right.
- Use virtual Getter instead of mVehicle in base class. In the base class there will be excessive Getter calls.
==================================================== =======================
Yes. I tried the template as shown below, but it cannot be compiled because errors like
"car.h: In the member function" virtual void Car :: State1 :: run (): car.h: 18: 12: error: "mVehicle has not been declared in this area."
// car.h #include <iostream> template <class T> class Car { public: class BaseState { public: explicit BaseState(T* vehicle) : mVehicle(vehicle) {} protected: T* mVehicle; }; class State1 : public BaseState { public: explicit State1(T* vehicle) : BaseState(vehicle) {} virtual void run() { mVehicle->x = 1; mVehicle->y = 2; mVehicle->doSomething1(); mVehicle->doSomething2(); processEvent(); } virtual void processEvent() { if (mVehicle->val > 2) { std::cout << "too large" << std::endl; } } }; class State2 : public BaseState { public: explicit State2(T* vehicle) : BaseState(vehicle) {} virtual void run() { mVehicle->x = 10; mVehicle->y = 20; processEvent(); } virtual void processEvent() { if (mVehicle->val > 20) { std::cout << "too large" << std::endl; } } }; virtual void doSomething1() { val += x * y; } virtual void doSomething2() { val += x + y; } protected: int x; int y; int val; }; // convertible.h #include "car.h" #include <iostream> class Convertible : public Car<Convertible> { protected: class State1 : public Car<Convertible>::State1 { explicit State1(Convertible* vehicle) : Car<Convertible>::State1(vehicle) {} // want to override functions in base class states virtual void processEvent() { if (mVehicle->val > 10) { std::cout << "too large" << std::endl; mVehicle->val = 10; } } }; // want to override some base class functions // and access some special variables // want to inherit other functions virtual void doSomething2() { z = 10; val += x + y + z; } protected: int z; };
If I use State1(Car* vehicle) instead of State1(T* vehicle) , there is an additional conversion error. What am I doing wrong?
If a program can determine that Convertible::State1::processEvent() should be executed, why can't it automatically distinguish mVehicle from Car* to Convertible* ? Apparently mVehicle points to a Convertible object when Convertible::State1::processEvent() . We do not need a template if there is an automatic cast.
source share