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" }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With