I have a base class which has a virtual function :
class Base {
...
virtual void myFunction() { assert(0 && "not implemented yet"); }
}
and a derived (template) class of Base :
DerviedClass.hpp :
Template<typename T>
class DerivedClass : public Base, public T {
...
void myFunction();
}
DerivedClass.cpp :
template <>
void DerivedClass<ClassA>::myFunction() {
//Something ClassA is suppose to do
}
This compiles. But when I try to instanciate a DerivedClass<ClassB> I get the error :
IProject.o:-1: erreur : undefined reference to `DerivedClass<ClassB>::myFunction()'
Why do I have this error? Why it does not take Base::myFunction instead of forcing me to implement a generic myFunction in DerivedClass or a specialized function DerivedClass::myFunction?
Note : the assert in myFunction is because ClassB is not supposed to call myFunction during runtime. For exemple if myFunction is getRadius, DerivedClass<Circle>::getRadius() is okay but DerivedClass<Square>::getRadius() should not be called.
Note 2 : The other topics I found were not clear about this point
Why it does not take Base::myFunction instead of forcing me to implement a generic myFunction in DerivedClass or a specialized function DerivedClass::myFunction?
You forced that yourself, by the declaration:
void myFunction();
Consider fully specializing the class template, which will generate classes conditionally with or without overriding myFunction, e.g.:
template <typename T>
class DerivedClass : public Base, public T {
// not overriding
};
template <>
class DerivedClass<ClassA> : public Base, public ClassA {
void myFunction() override;
};
template <>
void DerivedClass<ClassA>::myFunction() {
// something ClassA is supposed to do
}
If there's some common stuff, you can put it in:
template <typename T>
class DerivedClassCommons : public Base, public T {
// common stuff
};
and then refactor DerivedClass to use single inheritance of this class template.
That's it for your question, but as others were noting, I think you have a bigger, design problem.
Another method to fix the compiler error (not the design error) is to move the definition of myFunction to the derived template:
class Base {
virtual void myFunction() = 0;
}
template<typename T>
class DerivedClass : public Base, public T {
void myFunction() {
throw "not implemented, go away";
}
}
and then specialise only the methods you need:
template <>
void DerivedClass<ClassA>::myFunction() {
//Something ClassA is suppose to do
}
The function is already declared for all types. Definition might come from anywhere, including other compilation units. You'll only need the definition when the function is referred - and your virtual function is (implicitly) referred during construction.
Related
I am working on a C++ program. For one of the use case, I have a class which is derived from its template class. So, I'm wondering how we can call the base class method inside the derived class method?
Example:
template <typename base>
struct derived : public base
{
void aFunction()
{
// need to call a base function() here
}
};
One of the way could be something like base::aBaseFunction(), but I am not sure?
I am new to OOP programming, so looking forward to learning a new concept through this problem statement.
If you want to explicitly use the base's member, make the type explicit like you found:
template <typename base>
struct derived : public base
{
void aFunction()
{
base::function();
}
};
If you would rather have the usual unqualified-lookup behaviour, make this explicit instead:
template <typename base>
struct derived : public base
{
void aFunction()
{
this->function();
}
};
Both of these behave exactly like they do in non-templates.
I have the following code:
template <typename T>
class A {
public:
virtual void func() {
// Things that don't use T parameter.
}
};
class B : public A<int> {
public:
void func() {
A<int>::func();
// Working...
}
};
Basically, I want to override a virtual function defined in a class template from inside a class that inherits from a specialized version of such template (A).
Does this work in C++? Is it good practice? Also, is it ok to call the overridden method as I did in the overriding one? (please, note that, for compatibility with the toolchain I'm using, this is C++98)
Thank you.
I have a class template that implements a number of functions. I want to be able to also add specialized version of this class which has only a few functions that override those of the base, when a specific type is declared. I know I could achieve this with a class template and explicit specializations of it. However I also want to:
Have the explicit specializations uniquely named, similar to how a base and derived class are uniquely named.
Call the Base functions from an instantiated Derived object, either inside a Derived function, or explicitly as below with obj1.Foo
This is the (simplified) example code I am trying to make work:
In myClasses.h
template<typename T>
class Base
{
public:
void Foo (T& input);
virtual void Bar (T& input);
}
template<>
class Derived : public Base<int>
{
public:
void Bar (int& input) override;
}
In myClasses.cpp
template<typename T>
Base::Foo(T& input) { // Do something generic }
template<typename T>
Base::Bar(T& input) { // Do something generic }
template<>
Derived::Bar(int& input) { // Do something int-dependent }
In main.cpp
int main()
{
Base<int> obj1 = new Derived();
obj1.Foo(input); // Runs Base::Foo
obj1.Bar(input); // Runs Derived::Bar
}
However this code fails with the explicit specialization of non-template Derived error, among others. I've read a lot of StackOverflow threads to get me this far, but I haven't found any that have helped me make this compile. So my questions are:
Is combining class templates with class inheritance possible in this way?
Why does the compiler label the Derived class a non-template despite me explicitly using that keyword?
What is the correct syntax that will make this code work? (assuming what I am trying to do is possible)
EDIT: Following the suggesting of HTNW, I can turn Derived into a regular class by removing the template<> prefix. This will allow everything to compile up to obj1.Foo(input). It seems that the instantiated Derived class can't find or access the base Foo function.
Thanks to ravnsgaard and HTNW for the helpful suggestions which got me to a solution. The key was to remove the template<> keyword from the Derived class (because I wanted it to be a class and not a class template) and declaration of Base<int> at the end of the source file. So the working code looks like this:
In myClasses.h
template<typename T>
class Base
{
public:
void Foo (T& input);
virtual void Bar (T& input);
}
class Derived : public Base<int>
{
public:
void Bar (int& input) override;
}
in myClasses.cpp
template<typename T>
Base::Foo(T& input) { // Do something generic }
template<typename T>
Base::Bar(T& input) { // Do something generic }
Derived::Bar(int& input) { // Do something int-dependent }
template class Base<int>; // VERY IMPORTANT.
In main.cpp
int main()
{
Base<int> &&obj1 = Derived();
obj1.Foo(input); // Runs Base::Foo
obj1.Bar(input); // Runs Derived::Bar
}
In particular, without the template class Base<int>; declaration at the end of myClasses.cpp, the call to obj1.Foo will fail with an error complaining that Derived has no such function.
How can i pass object that inherited from template as this to function
please see the GameObj::GameObj constructor
i try to pass the GameObj that is inheriting the BaseGameObject template
but its not valid
template<typename T>
class BaseGameObject
{
public:
BaseGameObject(){};
virtual ~BaseGameObject(){};
static T* create(IImageComponent* imageComponent)
{
}
protected:
IImageComponent* m_IImageComponent;
};
class GameObj :public BaseGameObject<GameObj>
{
public:
GameObj(IImageComponent* imageComponent);
virtual ~GameObj(){};
};
GameObj::GameObj(IImageComponent* imageComponent):m_IImageComponent(imageComponent)
{
m_IImageComponent->update(*this); //HERE IS THE PROBLEM IT ASK ME TO PASS TAMPLATE
}
class GameObjImageCompnent
{
public :
GameObjImageCompnent(const std::string &spritefilename);
virtual void update(BaseGameObject& baseGameObject);
private:
std::string m_spritefilename;
};
GameObjImageCompnent::GameObjImageCompnent(const std::string &spritefilename):
m_spritefilename(spritefilename)
{
;
}
void GameObjImageCompnent::update(BaseGameObject& baseGameObject)
{
baseGameObject.setInitWithSpriteFrameName(m_spritefilename);
}
this link doesn't work for me :
Passing template classes as arguments to methods
BaseGameObject is a template. GameObjImageCompnent::update has a declaration virtual void update(BaseGameObject& baseGameObject);. That's wrong because BaseGameObject is not a type but a template.
Maybe you should change that declaration to: virtual void update(BaseGameObject<GameObj>& baseGameObject);
If you need to be able to call that with different BaseGameObjects, you could make GameObjImageCompnent into a template as well:
template<class T>
class GameObjImageCompnent {
// ...
virtual void update(BaseGameObject<T>& baseGameObject);
If that's not an option, you probably need to inherit BaseGameObject from a non-template base class and and use that as your reference type. If a base class for BaseGameObject is not an option either, you need to rethink your design.
class IGameObject {
public:
virtual ~IGameObject() {}
// any other virtual functions that are needed
};
template<typename T>
class BaseGameObject: public IGameObject {
//...
class GameObjImageCompnent {
// ...
virtual void update(IGameObject& baseGameObject);
You seem to be using CRTP. See the pitfalls section:
One issue with static polymorphism is that without using a general base class like "Shape" from the above example, you cannot store your derived classes heterogeneously as each CRTP base class is a unique type. For this reason, it's likely that you'll want to inherit from a shared base class with a virtual destructor, like the example above.
I think that limitation also applies to passing objects of derived classes to a function through a heterogeneous reference.
Have a base class A, and a derived class B which overrides function template Func:
class A
{
A() {...};
~A() {};
template <class T>
void Func(const String &sInput, T &tResult)
{...}
};
class B : public A
{
B() {...}
~B() {};
template <class T>
void Func(const String &sInput, T &tResult)
{...}
};
(Note that Func is non-virtual, given the lack of support in C++ for templated virtual functions.)
Now have a mainprog API, class M:
class M
{
M(boost::shared_ptr<A> &pInterfaceInput): pInterface(pInterfaceInput)
{}
template <class T>
Evaluate(const String &sInput, T &tResult)
{
pInterface->Func<T>(sInput, tResult);
}
private:
const boost::shared_ptr<A> pInterface;
};
I want the function Evaluate here to support calls to functions on base class A or any of its derived classes (such as B). This class was written with polymorphism in mind before I re-designed class A and B to have templated functions.
Now the problem here is that if I pass a shared pointer of the base type to the derived type then Func of the base class will be called, not the derived class being pointed to.
How do I get around the lack of dynamic polymorphism here?
I've considered making class M a class template on the shared pointer type and having a static_cast in the constructor to ensure this type is of the base class type (A) or of a derived class.
What's the nicest way to do this? I'd prefer not to modify classes A and B to get around this problem but all suggestions are welcome.
Thanks.
Sounds like a double dispatch problem. Perhaps this would be a good place to implement the visitor pattern?
For example, create a class Evaluator, and for each T a subclass ConcreteEvaluator<T>. Give A and B methods that visit the Evaluator. Something like:
class Evaluator
{
virtual void visit_A(A* object);
virtual void visit_B(B* object);
};
template <typename T>
class ConcreteEvaluator : public Evaluator
{
public:
String* input_reference;
T& result_reference;
ConcreteEvaluator(String& input_reference_,T& result_reference_) :
input_reference(input_reference_),
result_reference(result_reference_) {}
virtual void visit_A(A* object) {
object->Func(input_reference,result_reference);
}
virtual void visit_B(B* object) {
object->Func(input_reference,result_reference);
}
}
class A
{
...
virtual void apply_evaluator(Evaluator *eval) {eval->visit_A(this);}
...
}
class B
{
...
virtual void apply_evaluator(Evaluator *eval) {eval->visit_B(this);}
...
}
For each subclass of A, a new method must be added to ConcreteEvaluator, so that this technique works best if A's class hierarchy is stable. And for each subclass of A, it must have an apply_evaluator function defined properly.
On the other hand, this may be total overkill. For about the same amount of work, you could always just pay the price to update M::Evaluate:
class M
{
...
void Evaluate(const String& sInput, T& tResult)
{
// try to downcast to each subclass of A. Be sure to check
// sub-subclasses first
try
{
dynamic_cast<B*>(pInterface.get())->Func(sInput, tResult);
return;
}
catch (std::bad_cast& ) { }
...
// nothing worked. It must really be an A
pInterface->Func(sInput,tResult);
}
...
};
I've show in the question Templatized Virtual function how to use type erasure to get some of the effects of virtual member function. Depending on what you want to do in Func(), you can use the same technique here.