I'm having trouble passing a class DerivedObject
(part of class DerivedClass
derived from template class BaseClass
) derived from BaseObject
(part of template class BaseClass
) as a template argument to template class BaseClass
.
This way, both Base and Derived classes have the access to the object pool, that can contain derived objects. This sounds a bit confusing, so here is the example:
template <class TDerivedClass, class TDerivedObject>
class BaseClass
{
protected:
class BaseObject
{
// Class implementation
}
void foo()
{
static_cast<TDerivedClass*>(this)->foo();
}
std::vector<TDerivedObject*> m_objectPool;
};
The above is the base class implementation.
error C2065: 'DerivedObject' undeclared identifier
The above error is cause by the first line of the class definition bellow:
class DerivedClass : public BaseClass<DerivedClass, DerivedClass::DerivedObject>
{
protected:
class DerivedObject : public BaseObject
{
// Class implementation
}
void foo()
{
// Method implementation
}
};
Is there a way to do this? If not, is there a better solution that would give me the same / similar functionality?
It is possible to inherit from a template class. All the usual rules for inheritance and polymorphism apply. If we want the new, derived class to be generic it should also be a template class; and pass its template parameter along to the base class.
The Template Parameters tool is available for viewing template parameter usage in articles. It works with TemplateData to show the frequency of parameter name usage in a template's mainspace transclusions, along with whether or not each parameter is listed in that template's TemplateData code as a supported parameter.
" typename " is a keyword in the C++ programming language used when writing templates. It is used for specifying that a dependent name in a template definition or declaration is a type.
You can derive classes using any of the three access specifiers: In a public base class, public and protected members of the base class remain public and protected members of the derived class. In a protected base class, public and protected members of the base class are protected members of the derived class.
At this point
class DerivedClass : public BaseClass<DerivedClass, DerivedClass::DerivedObject>
The compiler has not seen DerivedClass::DerivedObject
so you get an undeclared identifier error. As they type has not been seen you cannot use it as a template parameter. You don't get one for DerivedClass
as you already have declared DerivedClass
as a class
.
You could change you base class and have it store a std::vector<BaseObject*>
in it and if you do that then you can change your code to:
template <class TDerivedClass>
class BaseClass
{
protected:
class BaseObject
{
// Class implementation
};
void foo()
{
static_cast<TDerivedClass*>(this)->foo();
}
std::vector<BaseObject*> m_objectPool;
};
class DerivedClass : public BaseClass<DerivedClass>
{
protected:
class DerivedObject : public BaseObject
{
// Class implementation
};
void foo()
{
// Method implementation
}
};
Here is one way of doing something similar to what was requested:
#include <vector>
using std::vector;
template <class TDerivedClass, class TDerivedObject>
class BaseClass
{
public:
class BaseObject
{
// Class implementation
};
protected:
// void foo()
// {
// static_cast<TDerivedClass*>(this)->foo();
// }
// std::vector<TDerivedObject*> m_objectPool;
};
class DerivedClass;
class DerivedObject : public BaseClass<DerivedClass, DerivedObject>::BaseObject
{
// Class implementation
};
class DerivedClass : public BaseClass<DerivedClass, DerivedObject>
{
public:
void foo()
{
// Method implementation
}
};
From your example code, I get the impression that you want to provide different implementations for different base classes. Is there any special reason for using templates? If not, you could use classic polymorphism instead:
class BaseClass
{
class BaseObject {};
virtual ~BaseClass() {} // <- do not forget to provide virtual dtor!
virtual void foo() = 0;
std::vector<BaseObject*> m_objectPool;
};
class DerivedClass : public BaseClass
{
class DerivedObject : public BaseObject {/*...*/};
virtual void foo(){/*...*/}
};
Again, BaseObject would offer virtual or pure virtual functions - as you need.
One thing, however, you lose this way: the guarantee that in the vector there are always the objects of one specific BaseObject sub-type. If this matters for you, you could protect the pool and only allow to add new BaseObjects via DerivedClass. If this is not applicable, I might think up another solution from within BaseClass.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With