Using virtual methods in class derived from templated base class - c++

Let's consider following example:
template<std::size_t F>;
class GenericColor
{
public:
std::array<int, F> colorComponents;
virtual void invertColor();
}
class RGBColor : public GenericColor<3>
{
void invertColor();
}
class CMYKColor : public GenericColor<4>
{
void invertColor();
}
How would I use virtual methods when my base class is templated? Is it even possible?
GenericColor *color = new CMYKColor();
Code below doesn't work. I think that RGBColor and CMYKColor have different base class and it causes the problem. Is there any workaround?

You're right that the two derived classes have different base classes (different specializations of the GenericColor template). Both happen to define a virtual function named invertColor, but the two are not related as far as the compiler is concerned.
One solution would be to move invertColor() into its own class and derive GenericColor<> from that. That way, both RGBColor and CMYKColor would "mean the same thing" when they say invertColor.
struct IGenericColor
{
virtual ~IGenericColor() = 0 {}
virtual void invertColor() = 0;
};
template<std::size_t F>
class GenericColor : public IGenericColor
{
public:
std::array<int, F> colorComponents;
virtual void invertColor(); // maybe you don't need an override here?
};
// rest as before
aschepler's comment about separating out ColorComponents instead and using multiple inheritance/composition seems like a good idea too; probably a better one if it makes sense for your situation.

GenericColor is not a class, not the way you have the hierarchy defined above. You can generate GenericColor<> classes based on the class template, but each of them is a distinct class.
Virtual functions should work properly within the inheritance "silo" defined by each template specialization; in other words, CMYKColor::invertColor() should properly override GenericColor<4>::invertColor().

Related

Calling base class method in derived class without specifying base class name

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();
}
};

Inheriting from both an interface and an implementation C++

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

can i pass object class that is inherited from template class?

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.

Overriding a pure virtual function from templated classes

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;
}
};

Inheriting templated base class methods in a templated subclass in C++ without listing every method

In Java, there is a detailed generic class hierarchy for containers. Java defines interfaces like ICollection<T> which is inherited by ISet<T> which is inherited by IList<T> and implemented by ArrayList<T>. I would like to create a similar hierarchy in a C++ library I am creating.
Using C++ templates however, makes this very cumbersome. For example, say I define an ISet<T>:
template<typename T>
class ISet
{
public:
virtual ~ISet() = 0;
virtual void add(T e) = 0;
virtual size_t size() = 0;
virtual bool isEmpty()
{
return size() == 0;
}
};
Then, if I wanted to make a List<T> which implements ISet<T>, I would have to list in the class definition every method that I wanted to inherit but not override, in order to let me later call it without something messy like alist::ISet<T>->isEmpty():
template<typename T>
class List : public ISet<T>
{
public:
...
void add(T e)
{
...
}
virtual sz size()
{
...
}
using ISet<T>::isEmpty; //well this is annoying
};
I understand the reason for this, and "why doesn't this work the way I expect it to?" has been answered in these qeustions: here and here.
My question is, is there a clean (or even any!) way to achieve this without having to explicitly list every inherited but not overridden method in the base class?
What I would really like would be something I could put in List<T> like:
using ISet<T>::*;
which would make all of the methods in ISet<T> dependent in the class definition of List<T>, and would alias them to List<T>::functionName.
Please tell me there is SOME way to achieve this without having to update every inheriting class's list of using directives each time I change one of my templated interfaces!
Do I have to resort to a preprocessor define of using directives defined along with the interface? Arrrrgghhhh!
This statement is incorrect:
... would have to list in the class definition every method that I
wanted to inherit but not override, in order to let me later call it
without something messy like alist::ISet->isEmpty():
Try to compile following code:
template<class T>
class Base {
public:
virtual void f1();
virtual void f2();
};
template<class T>
class Derived : public Base<T> {
public:
virtual void f1();
};
void foobar()
{
Derived<int> d;
d.f1();
d.f2();
}
If you mean that you want to access base class methods or members on derived class, you can simply do that more explicit way:
template<class T>
class Derived : public Base<T> {
public:
virtual void f1() { this->f2(); }
};
That is not messy and works as you asked, just little bit more explicit (some says it is good idea to always use this-> explicitly).