Question

What I want to do is give some classes in an existing hierarchy the ability to reinitialize one of their base classes via a member function. I know this would be a bad design decision if starting from a green field. I want to know if there are any tricks to get it to work any way.

Here is my naive attempt:

class Base {
    const int i_;
    std::unique_ptr<int> ui_;
public:
    Base() :i_{ 0 }{}
    Base(int i) :i_{ i }{}
    Base(Base && other) :i_{ other.i_ }, ui_{ std::move(other.ui_) }{}
    virtual void f(){
        std::cout << "Base f";
    }
    virtual ~Base(){
        std::cout << "Base dtor";
    }
};

class Derived : public Base {
public:
    virtual void f(){
        std::cout << "Derived f";
    }
    void reinitializeBase(Base && other){
        static_cast<Base*>(this)->Base::~Base(); //only call bases dtor
        new (static_cast<Base*>(this)) Base(std::move(other));
    }
    virtual ~Derived(){
        std::cout << "Derived dtor";
    }
};

the problem is obviously that the base classes constructor corrupts the pointer to vtable (making it point to base rather than derived).

I am aware that the "right" way to do this would be to pass the parameters for bases constructor in through the constructor of the derived class. This is not possible because Derived classes are created by a factory which I cannot modify. I could also just move the contents of the unique pointer in without reconstructing the base but then I still couldn't modify the const int

EDIT: sorry I forgot to mention that I cannot modify the base class either.

Was it helpful?

Solution

No, you cannot.

And no hack you can do would be safer than modifying base.h for your own private use in a ABI compatible way and making base better behaved. This requires knowledge of your compilers ABI and all future ABIs your code would be compiled under, which is impossible for any non trivial project.

If your life depended on it, you could do it: but doing it reliably would require constant vigilence against ABI changes. In practice, I would change base, or do pImpl hiding of base, or stop using base.

OTHER TIPS

After receiving the new information: Write a Wrapper class that has as member de 'Base' class.

The wrapper can have set/get function to access/change the internal 'Base' class.

I would make a function Reset on the base class, this way you have more control about what you want to reinitialize

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top