I want to make an object that can be given or provide it's own implementation of some pure virtual base class. This object would have complete ownership of this implementation, so taking an rvalue in the constructor seemed like a good fit:
struct base_haver {
base_haver() : base_haver(derived{}) {} // Provides default implementation
base_haver(base && b) : mBase(b) {} // Caller provides implementation
void call_func() { mBase.func(); }
base & mBase;
};
However, given these dummy classes:
struct base {
virtual void func() = 0;
};
struct derived : public base {
virtual void func() override { }
};
I get an access violation exception when calling base_haver::call_func() after creating it with the parameterless constructor:
base_haver b;
b.call_func(); // <-- Access violation exception (this->mBase.**** was 0xFFFFFFFFFFFFFFFF)
But if I provide that same implementation I get no exception:
base_haver b(derived{}); // <-- Identical to default constructor
b.call_func(); // <-- No exception, works fine.
I found a similiar question at Take ownership of parameter by rvalue-reference, which seems to indicate I have the right idea. The difference in my case is that my member has to be a reference - since it's a pure virtual class my base_haver can only have a pointer or reference to it's implementation.
Am I misunderstanding something about rvalues? Why would the base_haver's default constructor cause base_haver::call_func() to result in an access violation exception?