Reputation: 1332
I have a base class that updates an extern reference, and I want to build an inherited class that would embed this reference as a member. A kind of default initialization of the reference.
I came up with the following solution:
#include<iostream>
class Statefull
{
public:
Statefull( int& ref ) : _base_ref(ref) {}
int& _base_ref;
// update the extern variable
void work() { std::cout << ++_base_ref << std::endl; }
};
class Stateless : public Statefull
{
public:
// use a temporary allocation
Stateless( int* p = new int() ) :
// we cannot initialize local members before base class:
// _dummy(), Statefull(_dummy)
// thus, initialize the base class on a ref to the temporary variable
Statefull(*p),
_tmp(p),
_dummy()
{
// redirect the ref toward the local member
this->_base_ref = _dummy;
}
int* _tmp;
int _dummy;
// do not forget to delete the temporary
~Stateless() { delete _tmp; }
};
int main()
{
int i = 0;
Statefull full(i);
full.work();
Stateless less;
less.work();
}
But the need of a temporary allocation in a default argument of the constructor seems quite ugly. Is there a more elegant way to achieve this kind of default initialization while keeping a reference in the base class constructor?
Upvotes: 3
Views: 1017
Reputation: 12413
Everything can be solved using some more classes
class StateForStateful
{
protected:
int state;
};
class Stateless: private StateForStateful, public Stateful // order is important
{
public:
Stateless():Stateful(this->state) {}
};
Upvotes: 0
Reputation: 234654
Well, the Stateless
class is violating the rule of three. But I'll assume that's because this is just sample code to exhibit the real problem.
Now, to actually address the problem: it's perfectly valid to bind a reference to an uninitialized variable, as long as its value is not used before initialization actually happens.
Stateless() : Statefull(_dummy), _dummy() {}
The present solution works, but it seems there's some misunderstanding about why it works.
// redirect the ref toward the local member
this->_base_ref = _dummy;
You cannot "redirect" references. You can only bind a reference once: upon initialization. Assigning to a reference assigns to the object it refers to. In this case, this->_base_ref = _dummy
is exactly the same as *_tmp = _dummy
: it assigns the value of _dummy
to *_tmp
. _base_ref
, however, still refers to *_tmp
(you can test this with assert(&_base_ref == tmp)
).
Upvotes: 4
Reputation: 3459
I think this might work:
StateLess(): Statefull(*new int) {}
~StateLess() { delete &_base_ref; }
You can't do without temporaries, but they don't have to be in the classes definitions.
Upvotes: 1