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();
}
};
Related
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
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().
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.
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).
i have a c++ class like the below one working at vc++ , but doesnt work anymore in linux gcc 4.7. And i have no idea how to make it work again.
test.h
template<typename a>
class test: public a
{
public:
void fun();
};
test.cpp
template<typename a>
void test<a>::fun()
{
template_class_method(); <-- this is a public method from template_class
}
template class test<template_class>;
template_class.h
class template_class {
public:
template_class();
virtual ~template_class();
void template_class_method();
};
template_class.cpp
#include "templateclass.h"
template_class::template_class() {
// TODO Auto-generated constructor stub
}
template_class::~template_class() {
// TODO Auto-generated destructor stub
}
void template_class::template_class_method() {
}
You need to qualify it with the base class name as:
a::template_class_method();
The qualification a:: is necessary because template_class_method exists in a. The C++ rule is that if the base is a class template or template argument, then all its members are not automatically visible to the derived classes. In order to help the compiler to find the member, you need to tell it to look for the member in the base class, for which you need to qualify the member which is of the form of base::member_function() or base::member_data.
In your case, since the base is a, and the member is template_class_method, so you have to write this:
a::template_class_method();
Note that such a base class is called dependent base class since it depends on the template argument.
I don't know why #Karthik T deleted the answer, but that answer was on the right path. You have several options
Use qualified name a::template_class_method()
template<typename a>
class test : public a
{
public:
void fun()
{
a::template_class_method();
}
};
Use class member access syntax this->template_class_method()
template<typename a>
class test : public a
{
public:
void fun()
{
this->template_class_method();
}
};
Make the base class method visible through using-declaration
template<typename a>
class test : public a
{
public:
using a::template_class_method;
void fun()
{
template_class_method();
}
};
Note that the first method will suppress the virtuality of template_class_method (in cases when it is virtual), so it should be used with caution. For this reason, method number 2 is preferred, since it preserves the natural behavior of template_class_method.
Your comment stating that this->template_class_method() "doesn't work" is unclear. It works without any problems. Moreover, as I said above, this is in general case a better option than using a qualified name.