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.
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.
When overriding a C++ virtual method, is there a way to invoke the base class method without specifying the exact base class name, in a similar way that we can do it in C# with the "base" keyword? I am aware that this could be in conflict with multiple inheritance, but I wonder if more modern versions of C++ have introduced such a possibility.
What I want to do is something like this:
class A
{
public:
virtual void paint() {
// draw something common to all subclasses
}
};
class B : public A
{
public:
virtual void paint() override {
BASE::paint();
// draw something specific to class B
}
};
I know that in B::paint() we can call A::paint(), I just want to know if there is a more "generic" way to call the base method without referring explicitly to class A.
Thank you in advance.
Andrea
No, there is no fancy keyword to access to the base class.
As some comments already mentioned, some proposals have been rejected by the standard committee.
Personally, in some contexts, I opt for a typedef/using directive; especially when my hierarchy has templated classes.
For instance:
template <typename T>
class A {};
template <typename U, typename T>
class B : public A<T> {
private:
using Base = A<T>;
public:
void foo() {
// Base::foo();
}
};
I have such hierarchy of classes:
template <class Type>
class CrtpBase
{
protected:
Type& real_this()
{
return static_cast<Type&>(*this);
}
};
template <class ChildType>
class Base : CrtpBase<ChildType>
{
public:
void foo()
{
this->real_this().boo();
}
};
class Derived1 : public Base<Derived1>
{
public:
void boo { ... }
};
class Derived2 : public Base<Derived2>
{
public:
void boo { ... }
};
The thing is, I want to use my classes in this way:
std::vector<Base*> base_vec;
base_vec.push_bach(new Derived1());
base_vec.push_bach(new Derived2());
.........
base_vec[0]->foo();
But this isn't possible, because base class for all derived classes is different (actually Base isn't a type at all, it's template). So, is there a way to use crtp with multiple derived classes, alongside with polymorphism?
Indeed there is, you need to add the appropriate non-template base class too:
class AbstractBase
{
public:
virtual ~AbstractBase() {}
virtual void foo() = 0;
};
template <class ChildType>
class Base : CrtpBase<ChildType>, public AbstactBase
{
void foo() override { this->real_this().boo(); }
};
Then, declare your vector as std::vector<AbstractBase*>.
This does indeed introduce the overhead of dynamic dispatch (which you were probably trying to avoid by using CRTP), but dynamic dispatch is the only way to get runtime polymorphism in C++.
It can still be beneficial, though. For example, if the implementation of foo is shared by all the derived classes, but calls into many different boo-style functions (with each derived class having a different implementation of those), you will only pay the dynamic dispatch cost once when invoking foo, and then all the calls made within foo are dispatched statically, CRTP-style.
On the other hand, if it's just one call to a boo-like function within foo, you may as well make boo virtual, put non-virtual foo into the base, thus getting rid of CRTP. The cost will be the same then: a non-virtual dispatch (foo) and a virtual one (boo).
Side note, you should strongly consider storing smart pointers in the std::vector; owning raw pointers are bad practice.
I have searched stack overflow but haven't found something that exactly answers my question. I have an interface class which contains only pure virtual functions which I would like to be implemented by classes which derive from this class.
I have an interface that I will call BaseInterface which defines functions that I would like to be overridden in all classes which derive from this interface. In this example, say there is only one pure virtual function called toImplement. I create a class called Base which inherits from BaseInterface and adds some functionality to the inherited pure virtual functions. Base is still an abstract class since it does not implement the functions in BaseInterface.
I have several classes which derive from Base which all benefit from the common functionality of Base but specify what happens when toImplement is run on their instances. These classes should all be concrete and satisfy all the requirements set by BaseInterface. Below I define one of these classes called Derived.
All of this works fine when BaseInterface and Base are not templated. The code compiles and runs fine without defining (1.) or implementing (2.) toImplement in Base.
However I would like toImplement to work with different types. From what I understand it is fine to have pure virtual functions in a templated class. I template BaseInterface and Base on some type T. When I don't define toImplement in Base (1.), I cannot compile since Base doesn't know which toImplement to use in tryUsingImplemented. If I now add the definition to Base, the code pre-compiles but the linker cannot find the implementation of Base::toImplement. Finally, if I both define and implement toImplement in Base (1. and 2.), the code compiles.
I don't like this because I have a dummy implementation of toImplement in Base and I never want this implementation to be run. Additionally, because Base implements toImplement, Derived is no longer required to implement it. This makes BaseInterface useless in my eyes.
Can sombody enlighten me on how to enforce the implementation of toImplement in Derived, without having to implement it in Base first if that is at all possible?
template <typename T>
class BaseInterface {
virtual void toImplement(T & t) = 0;
};
template <typename T>
class Base : public BaseInterface<T> {
bool m_useImplemented;
public:
explicit Base(bool useImplemented) : m_usedImplemented(useImplemented) {}
void tryUsingImplemented(T & t) {
if (m_useImplemented)
toImplement(t);
}
protected:
// 1: Defining toImplement pure virtual function in Base
virtual void toImplement(T & t);
};
// 2. Implementing a version of toImplement in Base which does nothing
template <typename T>
inline void Base<T>::toImplement(T & t) {
// do nothing
}
class Derived : public Base<int> {
public:
explicit Derived(bool useImplemented) : Base<int>(useImplemented) {}
protected:
// 3. implementing toImplement in Derived
void toImplement(T & t) {
std::cout << "Doing stuff for Derived" << std::endl;
}
};
For future reference, it would be helpful if you provided the compiler error message.
However, in this case I know. There are two errors in your code:
toImplement is private in BaseInterface.
The lookup in tryUsingImplemented will not look in the base class. You're facing the lookup in dependent bases problem. To fix it, write this->toImplement(t).
You need to declare toImplement as protected in BaseInterface if you intend to call it from a derived class. I have removed all the overriding methods from the derived classes and replaced the parameter type of Derived::toImplement with int, and it compiles fine. The latter is necessary because Derived is not a template, so you need to use the template parameter passed to Base.
#include <iostream>
template <typename T>
class BaseInterface {
protected:
virtual void toImplement(T & t) = 0;
};
template <typename T>
class Base : public BaseInterface<T> {
bool m_useImplemented;
public:
explicit Base(bool useImplemented) : m_useImplemented(useImplemented) {}
void tryUsingImplemented(T & t) {
if (m_useImplemented)
toImplement(t);
}
};
class Derived : public Base<int> {
public:
explicit Derived(bool useImplemented) : Base<int>(useImplemented) {}
protected:
// 3. implementing toImplement in Derived
void toImplement(int & t) {
std::cout << "Doing stuff for Derived" << std::endl;
}
};
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.