Suppose I have a base class like this:
class Abstract {
public:
/* This type should be the deriver of this class */
virtual DerivedType foo(void) = 0;
};
And I want DerivedType to be different depending on who derives from this class. In fact I want DerivedType to be the type that Derives from Abstract.
I realize that I could do something like this:
template<typename der_t>
class Abstract {
public:
virtual der_t foo(void) = 0;
};
And then it should be used like this:
class Derived : public virtual Abstract<Derived> { };
Unfortunately there is no way to force someone to pass in the right type in the template. That is someone could do this:
class Derived : public virtual Abstract<int> { };
So is there any better way to do this, or is there a way to force someone to pass in the right parameter?
The usual trick for CRTP's is to have a private constructor that only the passed-in class can access via a friend directive:
template <class Derived>
struct Crtp {
private:
friend Derived;
Crtp() = default;
};
It isn't perfect, but guards against errors.
Note : static_asserting is not a practical solution, because at the time Crtp is instantiated Derived is still incomplete, and can't be checked for base classes.
Related
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();
}
};
Suppose I want to implement abstract behavior in a base class that is inherited by all derived classes. For example, a function that clones an object, applies some modification to it and returns the cloned and modified object (e.g. transposition, duplication, etc). The following code uses an even simpler function that merely returns the object itself:
class Base
{
public:
virtual Base* yourself ()
{
return this;
}
};
class Derived : public Base
{
public:
...
};
void main()
{
Derived d;
auto result = d.yourself();
}
If I didn't miss something, result will be of type Base*, where the intention clearly is to get an object of type Derived*.
Is there a way to have yourself() return the intended value for all derived classes without overriding it in all places (actually the whole point of inheritance is to implement each behavior only once)?
This issue is fairly common, and you can get around it using templates. Something like this:
template <class T>
class Base
{
public:
virtual T* yourself ()
{
return dynamic_cast<T*>(this);
}
};
class Derived : public Base<Derived>
{
public:
...
};
It's called the Curiously recurring template pattern (CRTP)
I usually try to find answers here before I post anything, but I'm not even sure how to formulate my question.
So here's what I want to do... I want to define a Base Interface, and a Derived Interface. Then, I want to implement the Base Interface, with extra variables and methods. Finally, I want to implemented a Derived class, from the implemented Base Interface BUT ALSO from the Derived Interface. I don't know about you, but my head hurts.
If I do something like below, I get Ambiguous definitions under the DerivedFloat code since that code "sees" both the GetBaseValue method from the IBase, inherited through IDerivedFloat, as well as the GetBaseValue inherited from Base.
Surely, there must be a way to derive a class which uses the expanded features of the Base Implementation, as well as making sure it implements the required IDerivedFloat methods.
Now... This is a dummy example to show what I'm conceptually trying to achieve. It's not a real life example.
template <typename VALUE_TYPE>
class IBase
{
public:
virtual VALUE_TYPE GetBaseValue() const = 0;
};
class IDerivedFloat : public IBase<FLOAT>
{
public:
virtual void SetBaseValue(const FLOAT & value) = 0;
};
// Implementation of Base
template <typename VALUE_TYPE>
class Base : public IBase<VALUE_TYPE>
{
public:
VALUE_TYPE GetBaseValue() const { return m_BaseValue; }
protected:
VALUE_TYPE m_BaseValue;
}
// Uses expanded Base AND implements IDerivedFloat
class DerivedFloat : public Base<FLOAT>, public IDerivedFloat
{
public:
void SetBaseValue(const FLOAT & value) { m_BaseValue = value };
}
You can use virtual inheritance to work around this problem:
class IDerivedFloat : virtual IBase<FLOAT>
{
public:
virtual void SetBaseValue(const FLOAT & value) = 0;
};
template <typename VALUE_TYPE>
class Base : virtual IBase<VALUE_TYPE>
{
public:
VALUE_TYPE GetBaseValue() const { return m_BaseValue; }
protected:
VALUE_TYPE m_BaseValue;
}
Using virtual inheritance gives the derive class one instance of the base class members, instead of one from each time it exists in the class hierarchy.
Multiple inheritance is an issue precisely because of the ambiguity issue you ran into, but there are ways to get around it. You have to explicitly tell the compiler which super you are calling the ambiguous functions from, by leading the function call with the super's name and a double colon.
Example:
- C inherits from A and B.
- A and B both have add() function.
- In C, you have to say A::add() or B::add() to tell the compiler which one to use.
Link for details and more complete implementation: http://www.cprogramming.com/tutorial/multiple_inheritance.html
I have the following base template class.
template<typename T>
class Base {
public:
void do_something() {
}
};
It is intended to be used as a curiously recurring template pattern. It should be inherited like class B : public Base<B>. It must not be inherited like class B : public Base<SomeoneElse>. I want to statically enforce this requirement. If someone uses this wrong, I expect an error in the compiling phase.
What I'm doing is putting a static_cast<T const&>(*this) in do_something(). This way the class inheriting the template is or inherits from the class provided as the template parameter. Sorry for the confusing expression. In plain English, it requires B is or inherits from SomeoneElse in class B : public Base<SomeoneElse>.
I don't know if it's the optimal way to achieve this. Looks gross to me.
However I want to do more. I want to ensure B is SomeoneElse itself. How can I do that?
Make the constructor (or destructor) of Base private, and then make T a friend. This way the only thing that can construct/destruct a Base<T> is a T.
If your class contains some code that says:
T* pT = 0;
Base *pB = pT;
Then there will be a compiler error if T is not assignment-compatible with Base.
This kind of check is formalised in C++11 so you don't have to write it by hand and can get helpful error messages:
#include <type_traits>
template<typename T>
class Base {
public:
void do_something()
{
static_assert(
std::is_base_of<Base, T>::value,
"T must be derived from Base");
}
};
class B : public Base<B> { };
int main()
{
B b;
b.do_something();
}
As to ensuring that Base's type parameter is exactly the class that is deriving from it, that seems conceptually flawed. A class that is acting as a base class can't "talk about" the type that is inheriting it. It may be inherited more than once via multiple inheritance, or not at all.
Two good answers so far. Here is another which uses the idiom of generating custom access keys to certain methods (in this case a constructor). It provides an absolute guarantee of correct use while not exposing private methods in the base to the derived.
It can also be used to control access to other methods in the base class on a case-by-case basis.
template<class Derived>
struct Base
{
private:
// make constructor private
Base() = default;
protected:
// This key is protected - so visible only to derived classes
class creation_key{
// declare as friend to the derived class
friend Derived;
// make constructor private - only the Derived may create a key
creation_key() = default;
};
// allow derived class to construct me with a key
Base(creation_key)
{}
// other methods available to the derived class go here
private:
// the rest of this class is private, even to the derived class
// (good encapsulation)
};
struct D1 : Base<D1>
{
// provide the key
D1()
: Base<D1>(creation_key())
{}
};
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.