I have a question about style. I have a class (in my case an Option) that depends on the value of an exogenous object (Interest Rate). My goal is to create a abstract base class for the exogenous object (Rate) so that I can construct variations, say SimulatedRate or ConstantRate, that will work inside my depending class, Option.
However, I'm finding in C++, since I obviously cannot instantiate a abstract base class, I must store either a pointer or a reference to the base class. My concern is that when the instantiated exogenous objects go out of scope outside of the dependent class, my dependent class will be pointing to junk.
Is there a reasonable way to utilize polymorphism for this problem in C++?
My current code:
class Dependent
{
public:
Dependent(const Exogenous& exo) : exo_(exo) {}
double getSomething() const { exo_.interfaceMethod(); }
private:
Exogenous& exo_;
}
class Exogenous
{
public:
virtual double interfaceMethod() const=0;
}
class ExogenousVariationA
{
public:
virtual double interfaceMethod() const { return resultA; }
}
class ExogenousVariationB
{
public:
virtual double interfaceMethod() const { return resultB; }
}
sftrabbit has some good advice, to which I'd add:
virtual
clone()
method in the abstract base class (it's not a virtual base class - that's something else entirely); that method would be implemented in the derived interest rate classes, returning a pointer to a new independent interest rate object that can be owned by the Option; this is particularly useful if the objects contain data that changes as you use it (e.g. from calculations or caching)Separately, to use runtime polymorphism your
ExogenousVariationA
and ~B
classes must actually derive fromExogenous
, and the method you want to be polymorphically dispatched must bevirtual
. That looks like this:Your worry is valid. Since you are storing to a reference an object passed in by the client, you are trusting that client to keep the object alive while you need it. This can easily lead to problems. Of course, the same would be true if you used raw pointers to dynamically allocated objects. If the client does
delete
on the object before you're done with it, once again you have a problem.The solution is to force the client to give you some kind of responsibility over the lifetime of the object. The way to do this is to ask for a smart pointer. Depending on your problem, you may want a
std::unique_ptr
orstd::shared_ptr
. Use the former if you want to take ownership from the client or the latter if you want to share ownership with them. Let's say you choosestd::unique_ptr
, you would then define yourDependent
class as:The client would use this like so:
Now, when your client passes the
std::unique_ptr
to you, they're giving you ownership of the object. The object will only be destroyed when yourstd::unique_ptr
is destroyed (which will be when yourDependent
is destroyed, since it is a member).Alternatively, if you take a
std::shared_ptr
then the object will be destroyed once both the client's and yourstd::shared_ptr
s are destroyed.