accessing non-template base class virtual function from template derived class - c++

I'm trying to understand the template and inheritance. I have a base class as follows:
class Base
{
public:
virtual ~Base() {}
virtual void setId(u_int8_t id)
{
m_id = id;
}
private:
u_int8_t m_id;
};
and a derived template class as follows:
template <typename T>
class Data : public Base
{
public:
virtual void setId(u_int8_t id)
{
this->setId(id);
}
inline void setData(const T& data)
{
m_data = data;
}
inline T& data()
{
return m_data;
}
private:
T m_data;
};
this code compiles fine but crashes at run time. Why is this happening?

You get a stack overflow because setId keeps calling itself. To call the setId in the base class, use
virtual void setId(u_int8_t id)
{
Base::setId(id);
}

This function:
virtual void setId(u_int8_t id)
{
this->setId(id);
}
It is calling itself recursively, until the process runs out of stack space and you get a crash.
To call a function from the base-class you have to use the scope operator:
Base::setId(id);

The setId() function recursively calls itself forever. You want:
virtual void setId(u_int8_t id)
{
Base::setId(Id);
}

You don't actually need setId(u_int8_t id) in Data. The method is inherited from Base.
If you are intending to provide a different implementation in derived class, and use in this different implementation the implementation of the Base, then use Base::setId(id) (as Joachim Pileborg pointed out)
P.S.: Actually, there is nothing specific to templates in your question.

Related

C++ Implementing a pure virtual function over a template

I am trying to implement an abstract class (ElementHolder) over a Template (TElementHolder). The function virtual T* Fun2() seems to work fine but the function virtual void Fun(T* element); creates the following compile error:
source>:60:23: error: cannot declare variable 'fireHolder' to be of abstract type 'FireElementHolder'
60 | FireElementHolder fireHolder;
| ^~~~~~~~~~
<source>:51:7: note: because the following virtual functions are pure within 'FireElementHolder':
51 | class FireElementHolder : public TElementHolder<Fire>
| ^~~~~~~~~~~~~~~~~
<source>:22:22: note: 'virtual void ElementHolder::Fun(Element*)'
22 | virtual void Fun(Element* element) = 0;
|
Can someone explain to me why the two functions create different results?
And if I can make this work somehow?
I am not sure if Implementing a pure virtual function over a template is the correct way of saying what I am doing here.
source: https://godbolt.org/z/qEYdrYfYa
#include <iostream>
//------------------------------------------------------------------------------------------
class Element
{
public:
virtual ~Element() {}
virtual void Fun() = 0;
};
class Fire : public Element
{
public:
~Fire() {}
void Fun() { std::cout << "Fire" << std::endl; }
};
//------------------------------------------------------------------------------------------
class ElementHolder
{
public:
virtual ~ElementHolder() {}
virtual void Fun(Element* element) = 0;
virtual Element* Fun2() = 0;
};
template<class T>
class TElementHolder : public ElementHolder
{
public:
virtual ~TElementHolder();
virtual void Fun(T* element);
virtual T* Fun2();
};
template<class T>
TElementHolder<T>::~TElementHolder() {}
template<class T>
void TElementHolder<T>::Fun(T* element)
{
element->Fun();
}
template<class T>
T* TElementHolder<T>::Fun2()
{
std::cout << "Hello Fun2" << std::endl;
return new T();
}
class FireElementHolder : public TElementHolder<Fire>
{
};
//------------------------------------------------------------------------------------------
int main()
{
FireElementHolder fireHolder;
auto instance = fireHolder.Fun2();
fireHolder.Fun(instance);
instance->Fun();
}
There is a well-known problem with your design.
You have two parallel class hierarchies, Elements and ElelementHolders. You want each concrete ElementHolder to accept a pointer or reference to a corresponding Element. So you add a pure virtual function to the base class
class ElementHolder {
virtual void Fun(Element* element) = 0;
and override it in each derived class (I de-templatized your hierarchy for ease of exposition, there is a T instead of Fire in your code, but it doesn't really affect anything):
class FireHolder : public ElementHolder {
virtual void Fun(Fire* fire) { ... }
Which is a very natural and sensible choice.
Except that it doesn't work at all, because void Fun(Fire* fire) doesn't override void Fun(Element* element). They are completely independent functions.
Now how do you solve this problem? There are two very different ways.
Get rid of ElementHolder::Fun altogether.
Change void Fun(Fire* fire) to void Fun(Element* fire). Cast fire to Fire* inside.
How does one cope without ElementHolder::Fun? Simply, just don't call it ;) You cannot safely use it anyway. The signature Fun(Element*) says that any element can be passed. In fact you can only pass Fire* to a FireHolder, and any other element is an error (so the signature lies---not a good idea). If you only have an ElementHolder and an Element *, there is no guarantee you can call Fun.
If you absolutely must call ElementHolder::Fun, then #2 is your only option.

How to call private virtual base class implementation when overriding in child class

I have a class hierarchy like this:
class Base
{
public:
void start() { init(); }
private:
virtual void init() = 0;
};
class Default : public Base
{
private:
virtual void init() override {/*default implementation*/};
};
class Special : public Default
{
private:
virtual void init() override final {/*specialized implementation*/};
}
Which works alright if I call start() on an object of type Special;
Now I have a case where in the implementation in the Special class I want to call the implementation of the Default class.
Normally that would work with Default::init();, but will fail here due to the Defaults declaration of this is private.
Obviously one solution is to change this from private to protected, but I'd like to ask if there is another way? Rather than allowing any child to call this function directly, I'd like to limit this to calls that are initiated via virtual functions already defined in the Base or Default class.
Is there some option or modifier that would allow member function calls to be only allowed from child classes if they are within (the same) overriding virtual member functions?
C++ doesn't provide means to achieve this directly, so you'd have to work around, e. g. in piece of code below.
Well, if you absolutely want to. I personally would rather just fall back to making the functions protected, document what they are intended for and when to be called, and then just trust the deriving classes to do the stuff right. That in the end keeps the interfaces cleaner and doesn't rely on a rather unusual (and perhaps ugly) pattern (actually passing this twice).
class Base
{
public:
virtual ~Base() { }
void start()
{
InitProxy p(*this);
init(p);
}
protected:
class InitProxy
{
public:
InitProxy(InitProxy const&) = delete;
void init()
{
m_base.Base::init(*this);
}
private:
friend class Base;
Base& m_base;
InitProxy(Base& base)
: m_base(base)
{ }
};
private:
virtual void init(InitProxy& proxy) { }
};
class Derived : public Base
{
void init(InitProxy& proxy) override
{
proxy.init();
}
};
You could let the proxy accept a member function pointer, if you want to apply this constraint to more than one function, so you wouldn't have to re-write the proxy for every function separately. Possibly you'd need to make a template from then, if function parameters differ.
Forward declare Special, and make it a friend of Default:
class Base
{
public:
void start() { init(); }
private:
virtual void init() = 0;
};
class Special; // Forward declaration
class Default : public Base
{
private:
virtual void init() override {/*default implementation*/}
friend class Special; // Friend declaration
};
class Special : public Default
{
private:
virtual void init() override final {
Default::init();
/*Other implementation*/
}
};

template class inheritance syntax

My intention is to have some base class CBaseClass that, amongst other things, serves as a container to some members of type CBaseMember; then to derive a CDerivedClass : public CBaseClass that holds CDerivedMember : public CBaseMember.
I can't use a pointer to CBaseMember and initialize it with a CDerivedMember object in CDerivedClass because it's a multiple inheritance situation, CDerivedMember has an additional interface (a pure abstract base class) that is irrelevant to CBaseClass implementation but needs to be visible to CDerivedClass. Lots of dirty casting is something that I would very much like to avoid.
My solution to this problem was to make CBaseClass a template, like this:
//declaration
template <class Member>
CBaseClass
{
protected:
virtual void GenericMethod();
virtual void VirtualMethod() = 0;
Member* member;
};
//definition
template <class Member>
void CBaseClass<Member>::GenericMethod()
{
member->SomeMemberMethod();
}
and then to inherit CDerivedClass from it, like this:
//declaration
CDerivedClass : public CBaseClass<CDerivedMember>
{
protected:
virtual void VirtualMethod();
};
//definition
void CDerivedClass::VirtualMethod()
{
member->SomeDerivedMethod();
}
Predictably, this doesn't work (CBaseClass<CDerivedMember>::GenericMethod() is unresolved, for obivious reasons), but unfortunatly I don't know how to change my code to mean what I intend for it to mean.
Can anyone please explain how those things are done properly - or suggest another solution for my problem?
Thanks!
Well, you could keep the dirty typecasts at one place, encapsulated in your class. Therefore, it's not really dirty anymore.
class CBaseMember {
public:
virtual void SomeMemberMethod(){}
};
class CDerivedMember : public CBaseMember {
public:
virtual void SomeMemberMethod() { /* do other stuff */ }
virtual void SomeDerivedMethod() {}
};
//declaration
class CBaseClass
{
protected:
virtual void GenericMethod();
virtual void VirtualMethod() = 0;
CBaseMember* member;
virtual CBaseMember * getMember() {
return member;
}
};
//definition
void CBaseClass::GenericMethod()
{
getMember()->SomeMemberMethod();
}
//declaration
class CDerivedClass : public CBaseClass
{
protected:
virtual void VirtualMethod();
virtual CDerivedMember * getMember() {return static_cast<CDerivedMember *>(member);}
};
//definition
void CDerivedClass::VirtualMethod()
{
getMember()->SomeDerivedMethod();
}
In summary, you do the dirty typecasting inside the getMember() method of the derived class. At that point you should be sure that the type of the member is CDerivedMember anyway. So, as long as you know that the pointer you have is of type CDerivedClass you will have access to its CDerivedMember without typecasting. If you have to fall back to a CBaseClass pointer, you'll naturally fall back to the CBaseMember while accessing its member.
I suspect that you want to get rid of the templates, because the snippet you provided would work (if you added the class keyword to the declaration of your types).
If you want to avoid downcasts from CBaseMember* to CDerivedMember*, you can approach the situation with dynamic binding and covariance:
class CBaseClass {
private:
CBaseMember* const baseMember;
protected:
virtual CBaseMember* member() const {
// ^^^^^^^^^^^
return baseMember;
}
/* everything else you need here. Just never ever access `baseMember` directly */
};
class CDerivedClass : public CBaseClass {
private:
CDerivedMember* const derivedMember;
protected:
virtual CDerivedMember* member() const {
// ^^^^^^^^^^^^^^
return derivedMember;
}
/* everything else you need here. Just never ever access `derivedMember` directly */
};
However, this only works if you will never change the member to point somewhere else, because you cannot pull this trick with a setter: virtual void CBaseClass::member(CBaseMember*) cannot be overridden with virtual void CDerivedClass::member(CDerivedMember*).
Note that you will still be carrying the baseMember pointer in your CDerivedClass around, although it is never ever used. So if memory is important to you, this might not be viable.

C++ Inheritance with pure virtual functions

I'm trying to create a class that serves as a base object, which will then be sub-classed (=implemented) to serve various purposes.
I want to define one or more pure virtual functions, so that however subclasses the base class, is required and does not forget to implement them.
There is one caveat, the pure virtual function's signature includes the type of the base object. Once sub-classed, the function definition doesn't match the base classes definition anymore of course. E.g.:
class BaseItem
{
public:
virtual std::string getDifferences(const BaseItem& item) = 0;
}
So, in the derived class I'd like to do:
class DerivedClass : public BaseItem
{
public:
virtual std::string getDifferences(const DerivedClass& item) = 0;
private:
std::string derivedItemCustomObject;
}
which of course the compiler won't accept. I could make it a BaseItem of course, but then I can't utilize any objects in the derived class.
Do I have to use casting to accomplish this?
Please let me know if my intent/question is not clear.
There is NO need to change the function signature. Look at following:
class BaseItem
{public:
virtual std::string getDifferences(const BaseItem& item) = 0;
};
class DerivedClass : public BaseItem
{public:
virtual std::string getDifferences(const BaseItem& item) // keep it as it's
{
const DerivedClass& derivedItem = static_cast<const DerivedClass&>(item);
}
};
Can use static_cast<> without any fear because, DerivedClass::getDifferences() is called only for DerivedClass object. To illustrate,
BaseItem *p = new DerivedClass;
DerivedClass obj;
p->getDifferences(obj); // this always invoke DerivedClass::getDifferences
If you worry that sometime you might end up passing any other derived class object as an argument to the method, then use dynamic_cast<> instead and throw exception if that casting fails.
It's unclear what you're trying to achieve. Suppose that the compiler allowed you to do this (or you do this by the means of a cast), then it would open the following hole in the type system:
class BaseItem
{
public:
virtual std::string getDifferences(const BaseItem& item) = 0;
};
class DerivedClass : public BaseItem
{
public:
virtual std::string getDifferences(const DerivedClass& item)
{
item.f();
// ...
}
void f() const {}
};
class DerivedClass2 : public BaseItem
{
public:
virtual std::string getDifferences(const DerivedClass2& item) { ... }
};
void g()
{
BaseItem* x = new DerivedClass;
// oops, calls DerivedClass::f on an instance of DerivedClass2
x->getDifferences(DerivedClass2());
}
Your design is probably wrong.
I assume that the compiler accept but DerivedClass::getDifferences doesn't override BaseItem::getDifferences. Here is a way to achieve what you apparently want
template <typename T>
class DerivedHelper: public BaseItem {
public:
virtual std::string getDifferences(const BaseItem& item) {
getDifferences(dynamic_cast<const T&>(item));
}
virtual std::string getDifferences(const T& item) = 0;
};
class DerivedClass : public DerivedHelper<DerivedClass>
{
public:
// not more needed but providing it will hide getDifferences(const BaseItem& item)
// helping to statically catch some cases where a bad argument type is used.
virtual std::string getDifferences(const DerivedClass& item) = 0;
private:
std::string derivedItemCustomObject;
};
but be aware that there is a runtime check which will throw exceptions if the argument isn't of the correct class.
One way to accomplish this is to use a template and have the parameter be the type of the derived type
template <typename T>
class BaseItem {
public:
virtual std::string getDifferences(const T& item) = 0;
};
class DerivedClass : public BaseItem<DerivedClass> {
public:
virtual std::string getDifferences(const DerivedClass& item) {
// Implement it here
}
};
You should use cast from BaseItem to DerivedClass + runtime check if given BaseItem is a DerivedClass instance.

interfaces for templated classes

I'm working on a plugin framework, which supports multiple variants of a base plugin class CPlugin : IPlugin. I am using a boost::shared_ptr<IPlugin> for all reference to the plugins, except when a subsystem needs the plugin type's specific interface. I also need the ability to clone a plugin into another seprate object. This must return a PluginPtr. This is why CPlugin is a template rather than a straight class. CPlugin::Clone() is where the template paramter is used. The following are the class definitions I am using:
IPlugin.h
#include "PluginMgr.h"
class IPlugin;
typedef boost::shared_ptr<IPlugin> PluginPtr;
class IPlugin
{
public:
virtual PluginPtr Clone() =0;
virtual TYPE Type() const =0;
virtual CStdString Uuid() const =0;
virtual CStdString Parent() const =0;
virtual CStdString Name() const =0;
virtual bool Disabled() const =0;
private:
friend class CPluginMgr;
virtual void Enable() =0;
virtual void Disable() =0;
};
CPlugin.h
#include "IPlugin.h"
template<typename Derived>
class CPlugin : public IPlugin
{
public:
CPlugin(const PluginProps &props);
CPlugin(const CPlugin&);
virtual ~CPlugin();
PluginPtr Clone();
TYPE Type() const { return m_type; }
CStdString Uuid() const { return m_uuid; }
CStdString Parent() const { return m_guid_parent; }
CStdString Name() const { return m_strName; }
bool Disabled() const { return m_disabled; }
private:
void Enable() { m_disabled = false; }
void Disable() { m_disabled = true; }
TYPE m_type;
CStdString m_uuid;
CStdString m_uuid_parent;
bool m_disabled;
};
template<typename Derived>
PluginPtr CPlugin<Derived>::Clone()
{
PluginPtr plugin(new Derived(dynamic_cast<Derived&>(*this)));
return plugin;
}
An example concrete class CAudioDSP.h
#include "Plugin.h"
class CAudioDSP : CPlugin<CAudioDSP>
{
CAudioDSP(const PluginProps &props);
bool DoSomethingTypeSpecific();
<..snip..>
};
My problem (finally) is that CPluginMgr needs to update m_disabled of the concrete class, however as it is passed a PluginPtr it has no way to determine the type and behave differently according to the template paramater. I can't see how to avoid declaring ::Enable() and ::Disable() as private members of IPlugin instead but this instantly means that every section of the application now needs to know about the CPluginMgr class, as it is declared as a friend in the header. Circular dependancy hell ensues. I see another option, declare the Enable/Disable functions as private members of CPlugin and use boost::dynamic_pointer_cast<CVariantName> instead.
void CPluginMgr::EnablePlugin(PluginPtr plugin)
{
if(plugin->Type == PLUGIN_DSPAUDIO)
{
boost::shared_ptr<CAudioDSP> dsp = boost::dynamic_pointer_cast<CAudioDSP>(plugin);
dsp->Enable();
}
}
This however leads to lots of duplicate code with many multiple variants of the base CPlugin template. If anyone has a better suggestion please share it!
You can easily write :
class CPluginMgr;
class IPlugIn ..
{
friend CPluginMgr;
...
};
Only a predefinition is needed for friend.
I think your get in trouble trying to return a shared_ptr in clone method. Why don't you make use of covariant return types? What you are doing is a common idiom called Virtual Constructor.
class IPlugin
{
public:
virtual IPlugin* clone() = 0;
// ...
}
class CPluginMgr;
class CPlugin : public IPlugin
{
public:
virtual CPlugin* clone() = 0;
friend CPluginMgr; // as #Christopher pointed out
void Enable(bool enable) { m_disabled = !enable; }
// ...
}
class CAudioDSP : public CPlugin
{
public:
virtual CAudioDSP* clone();
// ...
}
CAudioDSP* CAudioDSP::clone()
{
return new CAudioDSP(*this); // assume copy constructors are properly implemented
}
Returning a shared_ptr may lead you to make errors (as early destruction of temparary objects) and I think is not usually a good idea.