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() {
           // use data of Car
           ...
           doSomething();
       }
       virtual void doSomething() {
       }
    }
    class State2 : public BaseState {
    }
    ...
}

class Convertible: public Car {
    class State1 : public Car::State1 {
       explicit State1(Convertible* vehicle) : Car::State1(vehicle) {}
       virtual void doSomething() {
           static_cast<Convertible*>(mVehicle)->foldTop();
       }
    }
    class State2 : public Car::State2 {
    }
    ...
    void foldTop() {}
}

所有状态都从BaseState派生,因此它们具有成员变量mVehicle来访问外部类变量。
但是,在每个派生类中,在每个状态的所有函数中,需要static_cast来访问派生类成员变量和函数。

有更好的解决方案吗?
  • 在每个派生类的状态中,添加另一个指针(例如Convertible * mConvertible)。每个状态都有指向相同对象的重复指针(mConvertible和mVehicle)。看起来不正确。
  • 在基类中使用虚拟Getter代替mVehicle。基类中将会有过多的Getter调用。

  • ================================================== =====================

    是的。我尝试了如下模板,但由于诸如以下错误而无法编译

    “car.h:在成员函数“虚拟无效的Car::State1::run()”中:
    car.h:18:12:错误:未在此范围内声明“mVehicle”
    ”。
    // 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;
    };
    

    如果我使用State1(Car* vehicle)而不是State1(T* vehicle),则存在其他转换错误。我究竟做错了什么?

    如果程序能够确定应该执行Convertible::State1::processEvent(),为什么它不能自动将mVehicleCar*转换为Convertible*?当推导mVehicle时,Convertible显然指向Convertible::State1::processEvent()对象。如果有自动转换,则不需要模板。

    最佳答案

    此实现不使用强制类型转换,重复的指针,虚拟 getter 或CRTP。它具有三个并行层次结构:

  • 汽车
  • 是纯抽象接口(interface)的抽象汽车状态
  • 具体的汽车状态,其中状态由汽车的实际行驶类型类型参数化。

  • 所以我们有
    Car                   Car::AbstractState                Car::State<C>
    |                     |                                 |
    +--- Convertible      +--- Convertible::AbstractState   +--- Convertible::State<C>
    |    |                |    |                            |    |
    |    +--- Racer       |    +--- Racer::AbstractState    |    +--- Racer::State<C>
    +--- Hybrid           +--- Hybrid::AbstractState        +--- Hybrid::State<C>
    

    每个具体状态都源自并实现相应的抽象状态。如果我们有一个指向Car*Convertible,并查询其状态,我们将得到一个Car::AbstractState*,它指向最终状态为Convertible::State<Convertible>的具体状态对象。但是,汽车层次结构的用户不知道也不关心模板机制。

    编码:
    #include <iostream>
    using namespace std;
    
    struct Trace
    {
        Trace(const char* s) : s (s)
        {
            cout << s << " start\n";
        }
    
        ~Trace()
        {
            cout << s << " end\n";
        }
    
        const char* s;
    };
    
    struct Car {
        struct AbstractState
        {
            virtual void run() = 0;
        };
    
        template <typename C>
        struct State : virtual AbstractState
        {
            explicit State(C* vehicle) : mVehicle(vehicle) {}
            virtual void run()
            {
                Trace("Car::State::run");
                doSomething();
            };
            virtual void doSomething()
            {
                Trace("Car::State::doSomething");
            }
            C* mVehicle;
        };
    
        virtual AbstractState* getState() { return new State<Car>(this); }
    };
    
    
    struct Convertible : Car {
    
        struct AbstractState : virtual Car::AbstractState
        {
            virtual void runBetter() = 0;
        };
    
        template <typename C>
        struct State : Car::State<C>, virtual AbstractState
        {
            using Car::State<C>::mVehicle;
            explicit State(C* vehicle) : Car::State<C>(vehicle) {}
            void doSomething()
            {
                Trace("Convertible::State::doSomething");
                Car::State<C>::doSomething();
                mVehicle->foldTop();
            }
    
            void runBetter()
            {
                Trace("Convertible::State::runBetter");
                run();
                doSomethingElse();
            };
    
            virtual void doSomethingElse()
            {
                Trace("Convertible::State::doSomethingElse");
            }
        };
    
        void foldTop()
        {
            Trace("Convertible::foldTop");
        }
    
        Convertible::AbstractState* getState() { return new State<Convertible>(this); }
    };
    
    int main ()
    {
        Car car;
        Convertible convertible;
        Car& car2(convertible);
    
        cout << "runing car\n";
        Car::AbstractState* carstate = car.getState();
        carstate->run();
    
        cout << "runing convertible\n";
        Convertible::AbstractState* convertiblestate = convertible.getState();
        convertiblestate->run();
    
        cout << "runing car2\n";
        Car::AbstractState* carstate2 = car2.getState();
        carstate2->run();
    }
    

    关于c++ - 访问虚函数中的派生类成员变量,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33010677/

    10-11 22:04