I have run into a bit of a tricky problem in some C++ code, which is most easily described using code. I have classes that are something like:
class MyVarBase { } class MyVar : public MyVarBase { int Foo(); } class MyBase { public: MyBase(MyVarBase* v) : m_var(v) {} virtual MyVarBase* GetVar() { return m_var; } private: MyVarBase* m_var; }
I also have a subclass of MyBase that needs to have a member of type MyVar because it needs to call Foo. Moving the Foo function into MyVarBase is not an option. Does it make sense to do this:
class MyClass : public MyBase { public: MyClass(MyVar* v) : MyBase(v), m_var(v) {} MyVar* GetVar() { return m_var; } private: MyVar* m_var; }
This seems to work but looks really bad and I’m not sure if it’s going to cause a memory leak or break a copy constructor. My other options might be to name the MyVar variable in MyClass something else but have it be equal to the m_var pointer in the base, or to templatise MyBase on the MyVar type.
All these options don’t seem ideal so I wanted to know if anyone else has run into a situation like this and if there is a good way to make it work.
The correct way to do this is to have the variable only in the base class. As the derived class knows it must be of dynamic type
MyVar, this is totally reasonable:Since MyVar is derived from MyVarBase, the different return-types of
GetVarwould still work if GetVar was virtual (as is the case here). Note that with that method, there must be no function inMyBasethat can reset the pointer to something different, obviously.Note that
static_castis the right cast in that case. Usingdynamic_cast, as proposed by one commenter, will tell the readers and users of GetVar thatMyBase::GetVar()could return a pointer to an object not of type MyVar. But that doesn’t reflect our intention, as you only ever pass MyVar. To be consequent is the most important thing in software development. What you could do is to assert it is non-null. It will abort at runtime with an error-message in debug-builds of your project: