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.
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
.