c++stateabstract-classunique-ptrmember-access

avoid member access for shared base state


Suppose I have a base class that is an abstract interface, and two derived classes, which inherit a certain state from the base class. I want to change which derived class I'm using at run-time, but I want to preserve the shared state.

class Base{
public:
virtual void abstract() = 0;
SharedState ss;
};

class Der1 : public Base{
Der1() = default;
virtual void abstract() {//bla bla};
Der1(SharedState &s){
ss = s;};
};

class Der2 : public Base{
Der2() = default;
virtual void abstract(){//bla bla 2};
Der2(SharedState &s){
ss = s;};
};

struct SharedState{
int x,y,z;
float x1,y1,z1; 
//etc...
}

I my handler code, I have a smart pointer that changes behaviour based on class type at run-time, hence the shared state constructor.

 //driver code
std::unique_ptr<Base> ptr = std::make_unique<Der1>();

I'm planning to change the type, but with such a constructor I can preserve the state. However it is highly annoying to preface every member of the shared state with ss., is there a way to avoid this, perhaps with a using declaration of some sort?

Edit: I know I can move the shared state in the base and make it static, but that leads to performance drops when I'm not using this interface.


Solution

  • This is an ugly answer, but is an answer, solves the "ss" problem and can be usefull.

    I overloaded the operator [] to directly return the values of your struct

    struct SharedState{
    int x,y,z;
    float x1,y1,z1; 
    //etc...
    };
    
    
    class Base{
    public:
    virtual void abstract() = 0;
    SharedState ss;
    public:
      int& operator[](const std::string rhs) 
      {                          
        if(rhs == "x") //Here you will manage all the struct members, probably a map
        return this->ss.x; // return the result by reference
      }
    };
    
    class Der1 : public Base{
    void abstract() override { };
    public:
    Der1(SharedState &s){
    ss = s;};
    };
    
    class Der2 : public Base{
    void abstract() override { };
    public:
    Der2(SharedState &s){
    ss = s;};
    };
    
    
    
    int main()
    {
      SharedState ss;
      ss.x = 100;
      std::unique_ptr<Base> ptr = std::make_unique<Der1>(ss);
      
      std::cout << (*ptr)["x"] << std::endl;
      (*ptr)["x"] = 5; // You can change it too 
      std::cout << (*ptr)["x"] << std::endl;
      
      std::unique_ptr<Base> ptr2 = std::make_unique<Der2>(ptr->ss);
      std::cout << (*ptr2)["x"] << std::endl;
    }