Consider the following abstract class AbstractEngine:
class AbstractEngine {
static void init();
static std::string getName();
};
And consider the following 2 implementor classes:
class Engine1 : public AbstractEngine {
static std::string getName();
};
class Engine2 : public AbstractEngine {
static std::string getName();
};
And, the init() function should call the correct getName() according to the type of class:
void AbstractEngine::init() {
std::cout << getName() << std::endl;
}
For example, If I call Engine1::init(), I would like it to call Engine1::getName() and not AbstractEngine::getName()
How can I make AbstractEngine::init() really to call the correct implementation of getName()?
You can use the CRTP, i.e. make AbstractEngine a template class, then when you inherit, inherit from AbstractEngine<EngineN>:
template <typename T>
class AbstractEngine {
public:
static void init() {
std::cout << T::getName() << std::endl;
}
};
class Engine1 : public AbstractEngine<Engine1> {
public:
static std::string getName() { return "Engine1"; }
};
class Engine2 : public AbstractEngine<Engine2> {
public:
static std::string getName() { return "Engine2"; }
};
Live Demo
If you also need some dynamic polymorphic behaviour, you can make a common non-template base class:
class AbstractEngine {
//I assume you would have some virtual functions here
};
template <typename T>
class AbstractEngineImpl : public AbstractEngine {
public:
static void init() {
std::cout << T::getName() << std::endl;
}
};
class Engine1 : public AbstractEngineImpl<Engine1> {
public:
static std::string getName() { return "Engine1"; }
};
class Engine2 : public AbstractEngineImpl<Engine2> {
public:
static std::string getName() { return "Engine2"; }
};
The getName() method should not be static. Neither the init() method.
You're trying to get polymorphic behaviour, but with static functions. This doesn't make any sense. By definition, polymorphic behaviour is associated with particular instance of objects - but static functions do not have an associated instance.
If you want polymorphic behaviour (as you tag suggests), consider this redesign:
class AbstractEngine {
virtual void init();
virtual std::string getName();
};
class Engine1 : public AbstractEngine {
std::string getName() override;
};
class Engine2 : public AbstractEngine {
std::string getName() override;
};
Related
I got an Abstract Baseclass which looks like this:
class AbstractClass {
public:
virtual ~AbstractClass() = 0 {}
std::string GetName() const { return m_Name; }
private:
std::string m_Name;
};
Now I got many derived Classes and I want to implement them like this
class DerivedClass1 : public AbstractClass{
public:
DerivedClass1() = default;
~DerivedClass1() = default;
private:
std::string m_Name = "DerivedClass1";
};
int main() {
DerivedClass1 class1;
std::cout << class1.GetName();
return 0;
}
I dont want to override GetName() everytime i derive a Class, is this possible?
Edit:
I got a Linker Error. Error LNK2019.
Use only one name, in the base class, and a constructor with a parameter:
class AbstractClass{
public:
AbstractClass(const std::string& name) : m_Name(name){}
std::string GetName() const { return m_Name; }
private:
std::string m_Name;
};
DerivedClass1 : public AbstractClass{
public:
DerivedClass() : AbstractClass("DerivedClass1") {}
};
int main(){
DerivedClass1 class1;
std::cout << class1.GetName();
return 0;
}
There seems to be no reason for making the base class abstract, but if you do need that, even a pure virtual destructor must have a definition, or you will get a linker error, because it's needed when destroying derived objects.
Also, if the destructor didn't exist, when would m_Name be destroyed?
class Abstract
{
public:
virtual ~Abstract() = 0;
};
Abstract::~Abstract() {}
This makes a class that can't be instantiated, but whose derived classes can still be destroyed.
That's not how you "override" GetName(). You can either make GetName() virtual and override it in your derived classes:
class AbstractClass {
public:
virtual ~AbstractClass() = default;
virtual std::string GetName() const { return "AbstractClass"; }
private:
std::string m_Name;
};
and:
class DerivedClass1 : public AbstractClass {
public:
DerivedClass() = default;
std::string GetName() const override { return "DerivedClass1"; }
};
Or you can set m_Name in your derived classes by passing it to the base class constructor:
class AbstractClass {
public:
AbstractClass(const std::string& name) : m_Name(name) {}
virtual ~AbstractClass() = default;
std::string GetName() const { return m_Name; }
protected: // protected not private
std::string m_Name;
};
and:
class DerivedClass1 : public AbstractClass {
public:
DerivedClass() : AbstractClass("DerivedClass1") {}
};
Or you can set it in the derived's class constructor:
class AbstractClass {
public:
virtual ~AbstractClass() = default;
std::string GetName() const { return m_Name; }
protected: // protected not private
std::string m_Name;
};
and:
class DerivedClass1 : public AbstractClass {
public:
DerivedClass() : AbstractClass() { m_Name = "DerivedClass1"; }
};
You get the link error because the destructor for AbstractClass needs to be defined even if it is empty.
AbstractClass::~AbstractClass()
{
// Compulsory virtual destructor definition,
// even if it's empty
}
LIVE on Wandbox
Regarding overriding getName: you do not have to. If you do not provide an implementation in the derived class, the one inherited one is used.
Code sugest that problem is how to get a class name? But this is not clearly stated in question (XY problem)
How to handle class name?
You can use RTTI:
class ClassName {
public:
virtual ~ClassName() {} // just to enable RTTI for all decendants
std::string getClassName() {
return typeid(*this).name();
}
};
https://wandbox.org/permlink/LvPdA37arMr0LFQW
But as you can see it adds some extra prefix (it is compiler depended). boost can clean it up:
https://wandbox.org/permlink/8XiB7yVOM0wYVxpl
This code demonstrates the problem:
class Base
{
public:
explicit Base(std::function<void()> const& printFunc) :
_printFunc(printFunc)
{
}
void print()
{
_printFunc();
}
private:
std::function<void()> _printFunc{};
private:
virtual void _print() = 0; // If this line is commented out, then
// `Subclass1::_print()` can be called.
};
class Subclass1 : public Base
{
public:
explicit Subclass1() :
Base([this]() { _print(); })
{
}
private:
void _print() /*override*/
{
std::cout << "Subclass1\n";
}
};
class Subclass2 : public Base, public Subclass1
{
public:
using fromLowestSubclass = Base;
public:
explicit Subclass2() :
Base([this]() { _print(); }), Subclass1()
{
}
private:
void _print() /*override*/
{
// Here is the problem:
Subclass1::print(); // or: static_cast<Subclass1*>(this)->print();
std::cout << "Subclass2\n";
}
};
int main()
{
Subclass2 sc2{};
sc2.fromLowestSubclass::print();
return 0;
}
In the Subclass2::_print method, the overriding _print method of Subclass1 should be called, but instead the Subclass1::print(); statement calls the current method again. This problem can be prevented if the statement virtual void _print() = 0; is commented out.
Why use of the virtual _print method prevents me from invoking the overloaded virtual method Subclass1::_print and what solution is there so that I do not have to do without virtual methods?
class Base
{
....
private:
virtual void _print() = 0;
}
This means: you can override _print, but you can't call it, only Base has right to call it.
Now:
class Base
{
public:
void print()
{
_printFunc();
}
does that, it calls _printFunc as a virtual function, which matches current object instantiation. It doesn't meter how print() was invoked.
Adding Subclass1:: as a prefix just changes name scope and doesn't have impact how method behaves. It has only have impact on name scope.
Now if virtual method has such prefix, then selecting name scope instruct compiler that you abandoning abstraction and you need to call specific method. In such case method is called without referring to a virtual table.
Double inheritance has no impact on this issue.
You can provide a helper method which you will be able to call from ancestor:
class Subclass1 : public Base
{
....
protected:
void sub1_print() // not virtual
{
std::cout << "Subclass1\n";
}
private:
void _print() /*override*/
{
sub1_print();
}
};
class Subclass2 : public Base, public Subclass1
{
....
private:
void _print() /*override*/
{
sub1_print();
std::cout << "Subclass2\n";
}
};
Consider the following:
class Base {
public:
virtual std::string getName() = 0;
...
};
class Derived1 : public Base {
public:
static std::string getClassName() { return("Derived1"); }
std::string getName() { return("Derived1"); }
...
};
class Derived2 : public Base {
public:
static std::string getClassName() { return("Derived2"); }
std::string getName() { return("Derived2"); }
...
};
The idea is that if you have the derived class passed as, say, a template parameter, then you can get its class name via getClassName, while if you have it passed as a pointer to base class, you can get the name via getName.
I have seem a lot of similar questions to this here but all of them seem to ask stuff like "how do I use a static virtual", "why don't static virtuals exist" and various stuff like that, and the answers seem to address that more than what I think the real underlying problem is, which is: how can I avoid having to repeat myself with that code and mentioning the name twice while using as little boilerplate as possible? (Don't Repeat Yourself, or DRY Rule)
I don't want a macro, either.
First off, you can re-use getClassName in getName:
class Derived1 : public Base {
public:
static std::string getClassName() { return("Derived1"); }
std::string getName() override { return getClassName(); }
...
};
Now, all definitions of getName() are identical, so you can put them in a macro to save on typing (and make them more future-proof):
#define GET_NAME() std::string getName() override { return getClassName(); }
class Derived1 : public Base {
public:
static std::string getClassName() { return("Derived1"); }
GET_NAME()
...
};
Or you can bundle getClassName in there as well:
#define GET_NAME(maName) \
static std::string getClassName() { return(maName); } \
std::string getName() override { return getClassName(); }
class Derived1 : public Base {
public:
GET_NAME("Derived1")
...
};
You say "I don't want a macro, either," but macros are a good tool for that, and I wouldn't see a single problem with using them like this. However, if that is not what you want, you can do it without them as well:
template <class Self>
struct GetName : public Base
{
std::string getName() override { return Self::getClassName(); }
};
class Derived1 : public GetName<Derived1> {
public:
static std::string getClassName() { return("Derived1"); }
...
};
class Derived2 : public GetName<Derived2> {
public:
static std::string getClassName() { return("Derived2"); }
...
};
Don't fear data:
class Base {
public:
std::string const Name;
Base(std::string Name) : Name(Name) { }
};
class Derived1 : public Base {
public:
static const std::string Name;
Derived1() : Base { Name } { }
};
const std::string Derived1::Name { "Derived1" }
Make a separate base class that has the single responsibility of providing a class name string:
class FakeRTTI
{
std::string class_name;
public:
FakeRTTI( std::string className ) : class_name(className) {}
getClassName() { return class_name; }
}
With which you can then do this in all classes that need your fake, inefficient, explicit, string-based RTTI:
class Bla : public FakeRTTI
{
public:
Bla() : FakeRTTI("Bla") {}
}
Pro's:
DRY: there is only one ever use of the string "Bla", in its constructor.
Single Responsibility Principle
No virtual function calls
Cons:
Multiple inheritance (is this is con, really?)
You're not using the efficient, standard, C++-based RTTI.
You're still using RTTI (it might well not be feasible to get rid of it, but it is a sign of code smell all the smell).
Another possible solution uses traits and type erasure as in the following example:
#include<string>
#include<iostream>
template<typename> struct NameTraits;
template<typename T>
struct tag {};
class Base {
using func = std::string(*)(void);
template<typename T>
static std::string name() {
return NameTraits<T>::name;
}
public:
template<typename T>
Base(tag<T>): nameF{&name<T>} {}
std::string getName() {
return nameF();
}
private:
func nameF;
};
struct Derived1: Base {
Derived1(): Base{tag<Derived1>{}} {}
};
struct Derived2: Base {
Derived2(): Base{tag<Derived2>{}} {}
};
template<> struct NameTraits<Derived1> { static constexpr char *name = "Derived1"; };
template<> struct NameTraits<Derived2> { static constexpr char *name = "Derived2"; };
int main() {
Base *base = new Derived1;
// Using base class
std::cout << base->getName() << std::endl;
// Using directly the type
std::cout << NameTraits<Derived2>::name << std::endl;
}
Pros:
Name is no longer part of the class and you can easily define a common trait for a family of classes (use simply the same tag for all of them)
You don't have any virtual method
You don't need two methods that do almost the same thing
Cons:
You have to explicitly specify the tag that carries the type to be used during construction
I am trying to convert some Python classes into c++ but am having some trouble. I have a Base class which has a class (static) variable and a method which returns it. I also have a derived class which overrides the class (static) variable like so,
In Python:
class Base:
class_var = "Base"
#classmethod
def printClassVar(cls):
print cls.class_var
class Derived(Base):
class_var = "Derived"
d = Derived()
d.printClassVar()
which prints out the desired derived class variable, "Derived". Any idea how I can get the same functionality in c++? I have tried but end up getting the class variable of the Base class.
In c++
class Base
{
public:
static void printStaticVar(){cout << s_var << endl;}
static string s_var;
};
string Base::s_var = "Base";
class Derived : public Base
{
public:
static string s_var;
};
string Derived::s_var = "Derived";
void main()
{
Derived d;
d.printStaticVar();
}
Write a virtual function which returns a reference to the static member:
class Base
{
public:
void printStaticVar() {cout << get_string() << endl;}
static string s_var;
virtual string const& get_string() { return Base::s_var; }
};
string Base::s_var = "Base";
class Derived : public Base
{
public:
static string s_var;
virtual string const& get_string() { return Derived::s_var; }
};
string Derived::s_var = "Derived";
void main()
{
Derived d;
d.printStaticVar();
}
Note that printStaticVar shouldn't be static.
You could also make the string static local inside the getter:
class Base
{
public:
void printStaticVar() {cout << get_string() << endl;}
virtual string const& get_string() {
static string str = "Base";
return str;
}
};
class Derived : public Base
{
public:
virtual string const& get_string() {
static string str = "Derived";
return str;
}
};
void main()
{
Derived d;
d.printStaticVar();
}
Another possibility might be:
class Base
{
const std::string var;
public:
Base(std::string s="Base") : var(s) {}
void printVar() { std::cout << var << std::endl }
};
class Derived : public Base
{
public:
Derived(std::string s="Derived") : Base(s) {}
};
There are two base classes have same function name. I want to inherit both of them, and over ride each method differently. How can I do that with separate declaration and definition (instead of defining in the class definition)?
#include <cstdio>
class Interface1{
public:
virtual void Name() = 0;
};
class Interface2
{
public:
virtual void Name() = 0;
};
class RealClass: public Interface1, public Interface2
{
public:
virtual void Interface1::Name()
{
printf("Interface1 OK?\n");
}
virtual void Interface2::Name()
{
printf("Interface2 OK?\n");
}
};
int main()
{
Interface1 *p = new RealClass();
p->Name();
Interface2 *q = reinterpret_cast<RealClass*>(p);
q->Name();
}
I failed to move the definition out in VC8. I found the Microsoft Specific Keyword __interface can do this job successfully, code below:
#include <cstdio>
__interface Interface1{
virtual void Name() = 0;
};
__interface Interface2
{
virtual void Name() = 0;
};
class RealClass: public Interface1,
public Interface2
{
public:
virtual void Interface1::Name();
virtual void Interface2::Name();
};
void RealClass::Interface1::Name()
{
printf("Interface1 OK?\n");
}
void RealClass::Interface2::Name()
{
printf("Interface2 OK?\n");
}
int main()
{
Interface1 *p = new RealClass();
p->Name();
Interface2 *q = reinterpret_cast<RealClass*>(p);
q->Name();
}
but is there another way to do this something more general that will work in other compilers?
This problem doesn't come up very often. The solution I'm familiar with was designed by Doug McIlroy and appears in Bjarne Stroustrup's books (presented in both Design & Evolution of C++ section 12.8 and The C++ Programming Language section 25.6). According to the discussion in Design & Evolution, there was a proposal to handle this specific case elegantly, but it was rejected because "such name clashes were unlikely to become common enough to warrant a separate language feature," and "not likely to become everyday work for novices."
Not only do you need to call Name() through pointers to base classes, you need a way to say which Name() you want when operating on the derived class. The solution adds some indirection:
class Interface1{
public:
virtual void Name() = 0;
};
class Interface2{
public:
virtual void Name() = 0;
};
class Interface1_helper : public Interface1{
public:
virtual void I1_Name() = 0;
void Name() override
{
I1_Name();
}
};
class Interface2_helper : public Interface2{
public:
virtual void I2_Name() = 0;
void Name() override
{
I2_Name();
}
};
class RealClass: public Interface1_helper, public Interface2_helper{
public:
void I1_Name() override
{
printf("Interface1 OK?\n");
}
void I2_Name() override
{
printf("Interface2 OK?\n");
}
};
int main()
{
RealClass rc;
Interface1* i1 = &rc;
Interface2* i2 = &rc;
i1->Name();
i2->Name();
rc.I1_Name();
rc.I2_Name();
}
Not pretty, but the decision was it's not needed often.
You cannot override them separately, you must override both at once:
struct Interface1 {
virtual void Name() = 0;
};
struct Interface2 {
virtual void Name() = 0;
};
struct RealClass : Interface1, Interface2 {
virtual void Name();
};
// and move it out of the class definition just like any other method:
void RealClass::Name() {
printf("Interface1 OK?\n");
printf("Interface2 OK?\n");
}
You can simulate individual overriding with intermediate base classes:
struct RealClass1 : Interface1 {
virtual void Name() {
printf("Interface1 OK?\n");
}
};
struct RealClass2 : Interface2 {
virtual void Name() {
printf("Interface2 OK?\n");
}
};
struct RealClass : RealClass1, RealClass2 {
virtual void Name() {
// you must still decide what to do here, which is likely calling both:
RealClass1::Name();
RealClass2::Name();
// or doing something else entirely
// but note: this is the function which will be called in all cases
// of *virtual dispatch* (for instances of this class), as it is the
// final overrider, the above separate definition is merely
// code-organization convenience
}
};
Additionally, you're using reinterpret_cast incorrectly, you should have:
int main() {
RealClass rc; // no need for dynamic allocation in this example
Interface1& one = rc;
one.Name();
Interface2& two = dynamic_cast<Interface2&>(one);
two.Name();
return 0;
}
And here's a rewrite with CRTP that might be what you want (or not):
template<class Derived>
struct RealClass1 : Interface1 {
#define self (*static_cast<Derived*>(this))
virtual void Name() {
printf("Interface1 for %s\n", self.name.c_str());
}
#undef self
};
template<class Derived>
struct RealClass2 : Interface2 {
#define self (*static_cast<Derived*>(this))
virtual void Name() {
printf("Interface2 for %s\n", self.name.c_str());
}
#undef self
};
struct RealClass : RealClass1<RealClass>, RealClass2<RealClass> {
std::string name;
RealClass() : name("real code would have members you need to access") {}
};
But note that here you cannot call Name on a RealClass now (with virtual dispatch, e.g. rc.Name()), you must first select a base. The self macro is an easy way to clean up CRTP casts (usually member access is much more common in the CRTP base), but it can be improved. There's a brief discussion of virtual dispatch in one of my other answers, but surely a better one around if someone has a link.
I've had to do something like this in the past, though in my case I needed to inherit from one interface twice and be able to differentiate between calls made on each of them, I used a template shim to help me...
Something like this:
template<class id>
class InterfaceHelper : public MyInterface
{
public :
virtual void Name()
{
Name(id);
}
virtual void Name(
const size_t id) = 0;
}
You then derive from InterfaceHelper twice rather than from MyInterface twice and you specify a different id for each base class. You can then hand out two interfaces independently by casting to the correct InterfaceHelper.
You could do something slightly more complex;
class InterfaceHelperBase
{
public :
virtual void Name(
const size_t id) = 0;
}
class InterfaceHelper1 : public MyInterface, protected InterfaceHelperBase
{
public :
using InterfaceHelperBase::Name;
virtual void Name()
{
Name(1);
}
}
class InterfaceHelper2 : public MyInterface, protected InterfaceHelperBase
{
public :
using InterfaceHelperBase::Name;
virtual void Name()
{
Name(2);
}
}
class MyClass : public InterfaceHelper1, public InterfaceHelper2
{
public :
virtual void Name(
const size_t id)
{
if (id == 1)
{
printf("Interface 1 OK?");
}
else if (id == 2)
{
printf("Interface 2 OK?");
}
}
}
Note that the above hasn't seen a compiler...
class BaseX
{
public:
virtual void fun()
{
cout << "BaseX::fun\n";
}
};
class BaseY
{
public:
virtual void fun()
{
cout << "BaseY::fun\n";
}
};
class DerivedX : protected BaseX
{
public:
virtual void funX()
{
BaseX::fun();
}
};
class DerivedY : protected BaseY
{
public:
virtual void funY()
{
BaseY::fun();
}
};
class DerivedXY : public DerivedX, public DerivedY
{
};
There are two other related questions asking nearly (but not completely) identical things:
Picking from inherited shared method names. If you want to have rc.name() call ic1->name() or ic2->name().
Overriding shared method names from (templated) base classes. This has simpler syntax and less code that your accepted solution, but does not allow for access to the functions from the derived class. More or less, unless you need to be able to call name_i1() from an rc, you don't need to use things like InterfaceHelper.