Initializing static const in a class that extends a template - c++

Consider this pseudocode:
class Foo {
public:
virtual int getID() const = 0;
}
template<typename T>
class Blah : public Foo {
public:
T data;
static const int ID; //static ID
int getID() const { return Blah<T>::ID; } //instance returns the ID
}
class Dude : public Blah<int> {
}
int Dude::ID = 10; //I want to define Blah<int>::ID here, but how?
int receive(const Foo& foo) {
if(foo.getID() == Dude::ID) {
cout << "Received a Dude" << endl;
}
}
This piece of code fails to compile because ISO C++ does not permit the ID in the Blah template to be defined as the ID in the Dude class. I understand why because I could have multiple classes that extend a Blah<int>.
I understand if I put template<typename T> int Blah<T>::ID = 10' in the Blah<T> impl that it will work...but that isn't what I want...I want the derived class to define the ID...
Do I have to push the ID and getID() into the derived class? I guess ultimately I'm interested in some RTTI so I can process the Foo appropriately. If anyone has a better pattern, I'm all ears.
EDIT
In response to some of the comments...I would like to uniquely identify classes that derive from Foo via some ID so I can compare the runtime id of some Foo object to a specific class id.
Thanks!

Make the static int ID; private, and provide GetID in public interface, make SetID a protected interface. But that is not a good solution, because all the derived class will share the same ID, which is not what you want.
A better way should be you use the id as the base class' template parameter, then class Derived : public Base<234>{} will work.
Or add virtual const int GetID() = 0 into Base class.

I think you can simply do this:
class Dude : public Blah<int> {
}
static const int Dude_ID; //declaration!
int receive(const Foo& foo) {
if(foo.getID() == Dude::Dude_ID) {
cout << "Received a Dude" << endl;
}
}
static const int Dude::Dude_ID = 10; // definition!
Similarly, define an ID for each derived class.
Yet another way to have an ID for each class is this:
template<typename T, int ID=1>
class Blah : public Foo {
public:
int getID() const { return ID; }
}
template<int ID=10>
class Dude : public Blah<int> {
public:
int getID() const { return ID; }
}

I found this answer that does exactly what I'm after...sorry if my question was confusing.
in C++, how to use a singleton to ensure that each class has a unique integral ID?

Related

Behavior of static variables in objects of derived classes [duplicate]

If I have something like
class Base {
static int staticVar;
}
class DerivedA : public Base {}
class DerivedB : public Base {}
Will both DerivedA and DerivedB share the same staticVar or will they each get their own?
If I wanted them to each have their own, what would you recommend I do?
They will each share the same instance of staticVar.
In order for each derived class to get their own static variable, you'll need to declare another static variable with a different name.
You could then use a virtual pair of functions in your base class to get and set the value of the variable, and override that pair in each of your derived classes to get and set the "local" static variable for that class. Alternatively you could use a single function that returns a reference:
class Base {
static int staticVarInst;
public:
virtual int &staticVar() { return staticVarInst; }
}
class Derived: public Base {
static int derivedStaticVarInst;
public:
virtual int &staticVar() { return derivedStaticVarInst; }
}
You would then use this as:
staticVar() = 5;
cout << staticVar();
To ensure that each class has its own static variable, you should use the "Curiously recurring template pattern" (CRTP).
template <typename T>
class Base
{
static int staticVar;
};
template <typename T> int Base<T>::staticVar(0);
class DerivedA : public Base<DerivedA> {};
class DerivedB : public Base<DerivedB> {};
They will share the same instance.
You'll need to declare separate static variables for each subclass, or you could consider a simple static map in which you could store variables that are referenced by derived classes.
Edit: A possible solution to this would be to define your base class as a template. Having a static variable defined in this template would mean that each derived class will have it's own instance of the static.
There is only one staticVar in your case: Base::staticVar
When you declare a static variable in a class, the variable is declared for that class alone. In your case, DerivedA can't even see staticVar (since it's private, not protected or public), so it doesn't even know there is a staticVar variable in existence.
The sample code given by #einpoklum is not working as it is because of the missing initialization of the static member foo_, missing inheritance in FooHolder declaration, and missing public keywords since we are dealing with classes. Here is the fixed version of it.
#include <iostream>
#include <string>
class A {
public:
virtual const int& Foo() const = 0;
};
template <typename T>
class FooHolder : public virtual A {
public:
const int& Foo() const override { return foo_; }
static int foo_;
};
class B : public virtual A, public FooHolder<B> { };
class C : public virtual A, public FooHolder<C> { };
template<>
int FooHolder<B>::foo_(0);
template<>
int FooHolder<C>::foo_(0);
int main()
{
B b;
C c;
std::cout << b.Foo() << std::endl;
std::cout << c.Foo() << std::endl;
}
I know that this question has already been answered but I would like to provide a small example of inheritance with static members. This is a very nice way to demonstrate the usefulness as well as what is happening with the static variables and the respective constructors.
FooBase.h
#ifndef FOO_BASE_H
#define FOO_BASE_H
#include <string>
class FooBase {
protected:
std::string _nameAndId;
private:
std::string _id;
static int _baseCounter;
public:
std::string idOfBase();
virtual std::string idOf() const = 0;
protected:
FooBase();
};
#endif // !FOO_BASE_H
FooBase.cpp
#include "FooBase.h"
#include <iostream>
int FooBase::_baseCounter = 0;
FooBase::FooBase() {
_id = std::string( __FUNCTION__ ) + std::to_string( ++_baseCounter );
std::cout << _id << std::endl;
}
std::string FooBase::idOfBase() {
return _id;
}
std::string FooBase::idOf() const {
return "";
} // empty
DerivedFoos.h
#ifndef DERIVED_FOOS_H
#define DERIVED_FOOS_H
#include "FooBase.h"
class DerivedA : public FooBase {
private:
static int _derivedCounter;
public:
DerivedA();
std::string idOf() const override;
};
class DerivedB : public FooBase {
private:
static int _derivedCounter;
public:
DerivedB();
std::string idOf() const override;
};
#endif // !DERIVED_FOOS_H
DerivedFoos.cpp
#include "DerivedFoos.h"
#include <iostream>
int DerivedA::_derivedCounter = 0;
int DerivedB::_derivedCounter = 0;
DerivedA::DerivedA() : FooBase() {
_nameAndId = std::string( __FUNCTION__ ) + std::to_string( ++DerivedA::_derivedCounter );
std::cout << _nameAndId << std::endl;
}
std::string DerivedA::idOf() const {
return _nameAndId;
}
DerivedB::DerivedB() : FooBase() {
_nameAndId = std::string( __FUNCTION__ ) + std::to_string( ++DerivedB::_derivedCounter );
std::cout << _nameAndId << std::endl;
}
std::string DerivedB::idOf() const {
return _nameAndId;
}
main.cpp
#include "DerivedFoos.h"
int main() {
DerivedA a1;
DerivedA a2;
DerivedB b1;
DerivedB b2;
system( "PAUSE" );
return 0;
}
If __FUNCTION__ is not working for you in your constructors then you can use something similar that can replace it such as __PRETTY_FUNCTION__ or __func__, or manually type out each class's name :(.
Alas, C++ has no virtual static data members. There are several ways to simulate this, more or less:
#GregHewgill's solution has you replicate the static variable in each derived class; this solution is simple, straightforward and doesn't introduce additional classes, but I don't like this one since it's verbose, and you have to be rather disciplined with it.
#MarkIngram suggested a CRTP-based solution, which saves you most of the typing; however, it messes up the inheritance structure, because what were previously subclasses of A are no longer really related as classes. After all, two templated types with the same name but different template arguments could be just any two types.
I suggest a different CRTP-based solution, using a mix-in class:
class A {
virtual const int& Foo() const = 0;
}
template <typename T>
class FooHolder {
static int foo_;
const int& Foo() const override { return foo_; }
}
class B : A, virtual FooHolder<B> { }
class C : B, virtual FooHolder<B> { }
The only thing you need to do in a subclass is also indicate the mix-in inheritance. There might be some virtual inheritance caveats I'm missing here (as I rarely use it).
Note that you either have to instantiate and initialize each subclass' static variable somewhere, or you can make it an inline variable (C++17) and initialize it within the template.
This answer was adapted from my answer to a dupe question.

Virtual methods with multiple argument types in C++

Lets say I have a base class A that I want to have a method getName that can take in either an integer or a string as the argument. So I create:
virtual string getName(int index) = 0;
virtual string getName(string key) = 0;
Now, I want to create two different subclasses B and C. B only needs the getName(int index) and C only needs the getName(string key).
However, if I dont overwrite both methods in both subclasses, I get an error. But if I do this, then B and C will have an empty methods because they dont need the other case of getName
How can I overcome this problem?
It sounds like you actually want two different interfaces: one that supports getName(int) and one that supports getName(string).
struct GetNameInt {
virtual string getName(int index) = 0;
};
struct GetNameStr {
virtual string getName(string key) = 0;
};
struct B : GetNameInt { /* ... */ };
struct C : GetNameStr { /* ... */ };
If you really need a single base class with the same interface, and you only know at run-time whether you'll need a string or an int, you might want to use std::variant:
struct GetName {
virtual string getName(std::variant<int, string>) = 0;
};
You're not using inheritance properly. I strongly recommend reading more about the SOLID principles.
You need to split the class A into two classes (interfaces) - Aa and Ab, where Aa would hold getName(int index) and would have getName(string key), like:
class A {
//does not define neither of the getName methods
}
class Aa {
virtual string getName(int index) = 0;
}
class Ab {
virtual string getName(string key) = 0;
}
class B : A, Aa {
//inherits from A and defines string getName(int index)
}
class C : A, Ab {
//inherits from A and defines string getName(string key)
}
Ok, the best I can come up with to keep a common parent between B and C while still preserving some type safety and compile time check:
struct CommonA //protect this if possible
{
template<class type>
string getGenericName(type index);
virtual ~CommonA() {}
};
template<class indexType>
struct A : CommonA
{
virtual string getName(indexType index) = 0;
};
struct B : A<int>
{
string getName(int index) override {cout << index << "\n"; }
};
struct C : A<string>
{
string getName(string index) override {cout << index << "\n"; }
};
template<class type>
string CommonA::getGenericName(type index)
{
cout << "generic call: \n";
return dynamic_cast<A<type>*>(this)->getName(index);
}
int main()
{
CommonA b = B();
CommonA c = C();
b.getGenericName(1);
c.getGenericName(string("hello world"));
}
Note that this solution is not a standard OOP solution but a template solution.
Edit: my templated A<> class is the same as Vittorio Romeo's solution using template instead of name pasting (name pasting is evil)
By simply don't making them pure virtual, but just virtual:
struct Blub
{
virtual void do1() {} // default definition
virtual void do2() = 0; //has to be overridden
};

(re)implement dynamic_cast

I am working in an ARM7 embedded environment. The compiler I am using does not support the full C++ functionality. One feature it does NOT support is dynamic type casting.
Is there a way to implement dynamic_cast<>()?
I looked for code using Google, but no luck so far. Any ideas? Any links?
UPDATE:
Due to the comments... I'm using the ARM(R) IAR C/C++ Compiler.
dynamic_cast is useful when casting away from the base class, something to be done as little as possible.
Assuming the instances when you want to do this are limited, then a virtual function like GetMessageType() in a base class returning a different value in each derived class will let you know what to static_cast down to.
Take a look at the COM concepts -- objects there have a method to return a pointer to a specific interface that is selected by an identifier not built into the compiler (in COM's case, a UUID).
Depending on your application, a simple integer may do:
class castable {
virtual bool cast_to(int desttype) = 0;
};
class type1 : public castable { public: static int const type = 1; };
class type2 : public castable { public: static int const type = 2; };
class impl : public type1, public type2 {
virtual void *cast_to(int desttype) {
switch(desttype) {
case type1::type: return static_cast<type1 *>(this);
case type2::type: return static_cast<type2 *>(this);
default: return 0;
}
}
};
Then, if templates work correctly:
template<typename T> T my_dynamic_cast(castable *obj) {
return reinterpret_cast<T>(obj.cast_to(T::type));
}
You can then create objects normally, and cast between base class pointers:
impl im;
type1 *t1 = &im; // Implicit, as it is a base class
type2 *t2 = my_dynamic_cast<type2 *>(t1);
The only difficulty here is assigning the identifiers.
It really depends exactly how much of dynamic_cast functionality you need.
Most often, I see dynamic_cast used to perform a checked conversion: dynamic_cast<Derived*>(p) will return 0 if ultimately p real type is not Derived*...
... but even this is quite complicated:
What if p is really EvenMoreDerived and not just Derived ?
What is p inherits from Base multiple times ?
And it can get even more hairy:
static_cast is not able to cross virtual inheritance boundaries.
static_cast is not suitable for cross-branches conversions (you have to pass through the common ancestor)
static_cast cannot emulate the dynamic_cast<void*>() conversion.
So, if you want a simple barebone functionality of checked conversion up the inheritance tree in case of single inheritance without virtual thrown in, then you can actually implement it in user-land.
Otherwise, without RTTI support, you will be quite stuck.
Example of simple (dumb ?) implementation, beginning with the support from the class hierarchy:
class Base {
public:
typedef size_t ID;
virtual ID getID() const = 0;
protected:
static ID NextID() { static ID = 0; return ID++; }
// much more stuff
};
class Derived: public Base {
public:
static ID GetID() { static ID id = Base::NextID(); return id; }
virtual ID getID() const { return GetID(); }
};
We can leverage this with:
template <typename To>
To* dyn_cast(Base* b) {
if (b and b->getID() == To::GetID()) { return static_cast<To*>(b); }
return 0;
}
However, this only work for one level. So, if MoreDerived inherits from Derived then:
MoreDerived md;
assert(dyn_cast<Derived>(&md)); // failure ...
so it really gets tricky here.
A possible approach is to check from the top of the hierarchy, to the bottom.
class Base {
public:
template <typename To>
bool isa() const {
return this->match(To::GetID());
}
protected:
typedef size_t ID;
static ID NextID() { static ID id = 0; return id++; }
virtual bool match(ID) const { return false; }
};
class Derived: public Base {
public:
static ID GetID() { static ID id = NextID(); return id; }
protected:
virtual bool match(ID id) const { return id == GetID() || Base::match(id); }
};
class MostDerived: public Derived {
public:
static ID GetID() { static ID id = NextID(); return id; }
protected:
virtual bool match(ID id) const { return id == GetID() || Derived::match(id); }
};
Slightly more complex, but now:
template <typename To, typename From>
To const* dyn_cast(From const* f) {
if (f and f->template isa<To>()) { return static_cast<To const*>(f); }
return 0;
}
template <typename To, typename From>
To* dyn_cast(From* f) { return const_cast<To*>(dyn_cast<To>((From const*)f)); }
Test case:
int main() {
Derived derived; MostDerived mostDerived;
Base* d = &derived, * md = &mostDerived;
if (dyn_cast<Derived>(d)) { std::cout << "Derived -> Derived: ok\n"; }
else { std::cout << "Derived -> Derived: ko\n"; }
if (dyn_cast<MostDerived>(md)) { std::cout << "MostDerived -> MostDerived : ok\n"; }
else { std::cout << "MostDerived -> MostDerived : ko\n"; }
if (dyn_cast<Derived>(md)) { std::cout << "MostDerived -> Derived : ok\n"; }
else { std::cout << "MostDerived -> Derived : ko\n"; }
if (dyn_cast<MostDerived>(d)) { std::cout << "Derived -> MostDerived: ko\n"; }
else { std::cout << "Derived -> MostDerived: ok\n"; }
}
In action at ideone.
It is still very incomplete compared to a true dynamic_cast though. But it should cover most uses already.
Isn't it possible to just cast your pointer and start using it as the other type of object?
Foo* f = new Foo();
f.baz();
Bar* b = (Bar*)f;
b.bop();

C++ unique static id and class name with base class

Having class TaskBase, each derived class of it must have name and unique id.
The TaskBase is something like below:
class TaskBase
{
public:
static const int id()
{
// return an unique id, for each object or derived class, HOW ??
}
static const string name()
{
// return class name for each derived class, HOW ??
// for example : "TaskBase" for this class
}
};
My try was :
template <typename DERIVED>
class TaskBase
{
public:
static const int id()
{
static const int id = reinterpret_cast<int> (typeid (DERIVED).name());
return id;
}
static const string name()
{
static string n;
if (!n.size())
{
int status;
char *realname = abi::__cxa_demangle(typeid (DERIVED).name(), 0, 0, &status);
n = realname;
free(realname);
}
return n;
}
};
I already read this, but i need the ability to have base pointer to each derived classes, something line below:
class MyTask1 : public TaskBase
{
};
MyTask1 myTask1, myTask2;
TaskBase *base = &myTask1;
class TaskBase
{
private:
const void* m_id;
string m_name;
public:
TaskBase(const void* m_id, string m_name): m_id(m_id), m_name(m_name)
{
}
const void* id() const
{
return m_id;
}
string name() const
{
return m_name;
};
};
template< typename DERIVED >
class TaskProxy: public TaskBase
{
public:
static const void* id()
{
//if you want to have for each object a unique id:
//return reinterpret_cast<void*>(this);
//just for each TaskProxy<????>:
return reinterpret_cast<const void*>(typeid( DERIVED ).name());
}
static string name()
{
return typeid( DERIVED ).name();
}
TaskProxy(): TaskBase(id(), name()) {}
};
Usage:
class MyTask1 : public TaskProxy< MyTask1 >
{
};
class MyTask2 : public TaskProxy< MyTask2 >
{
};
...
MyTask1 myTask1;
TaskBase *baseA = &myTask1;
MyTask2 myTask2;
TaskBase *baseB = &myTask2;
cout << "Name: " << baseA->name() << " Id:" << baseA->id() << endl;
cout << "Name: " << baseB->name() << " Id:" << baseB->id() << endl;
Which outputs this (with gcc 4.6):
Name: 7MyTask1 Id:0x401228
Name: 7MyTask2 Id:0x4011c0
I suggest implementing pure virtual methods for obtaining the class name and ID in the base class. The descendants would need to provide the unique names and IDs.
class TaskBase
{
public:
virtual std::string get_task_name(void) const = 0;
virtual unsigned long get_task_id(void) const = 0;
};
I took #VoidStar's suggest a step further and put the names into a (single) common class:
class TaskNames
{
protected:
static std::string get_tas1_name();
};
class Task1: public TaskBase, public TaskNames
{
//...
};
If you are following strictly standard C++, you may need to just bite the bullet and do some additional bookkeeping. Make an enum somewhere that stores all the classnames:
enum ClassID {
MYTASK1_CLASS,
MYTASK2_CLASS
};
It doesn't take that long to add a new classId when you make a new class.
I've done this before. It's sufficient for uniqueness to do what I describe above. But... if the enum values are set with a clever enough macro, you can encode the hierarchy of the classes, and implement dynamic cast and instanceof solely from the ClassID and a bitwise mask!

Stopping or Blocking Inheritance in C++

I would to block child classes from overriding a base method and have the child classes override a new method in a parental class. In other words, a child class of the base class blocks the base class methods and delegates to a new method that further child classes must override. I still want the base class method to be available.
Here is an example:
#include <iostream>
#include <string>
struct Base
{
virtual const std::string& class_name(void) = 0;
};
struct Level1
: public Base
{
private: // Prevent child classes from overriding
// the Base::class_name method
const std::string& class_name(void)
{
static std::string name;
name = "class" + class_name_from_level_1();
return name;
}
protected:
// This is the "new" or redirected class that child classes
// must override.
virtual const std::string& class_name_from_level_1(void) = 0;
};
struct Level2
: public Level1
{
static std::string name;
const std::string& class_name_from_level_1(void)
{
if (name.length() == 0)
{
name = "Level2";
}
return name;
}
};
int main(void)
{
Level2 lev2;
std::cout << lev2.class_name() << "\n";
return 0;
}
I am getting the following errors from g++:
$ g++ hiding_virt_methods.cpp -o hiding_virt_methods.exe
hiding_virt_methods.cpp: In function `int main()':
hiding_virt_methods.cpp:15: error: `virtual const std::string& Level1::class_name()' is private
hiding_virt_methods.cpp:43: error: within this context
In the above example, I want the following chain of execution for Level2:
Base::class_name() --> Level1::class_name_from_level_1() --> Level2::class_name_from_level_1()
Also, I only want to block inheritance of specific methods in the Base class. Protected and Private Inheritance affect all the public methods.
So how do I stop the chain of inheritance of specific Base methods at different levels in the inheritance tree?
Edit: Real world example.
I have an interface class Record. Class Record_With_Id inherits from class Record and adds an ID field. The class Record contains an accept_visitor method. Class Record_With_Id overrides accept_visitor to apply to the ID field, then calls a virtual method, record_with_id_accept_visitor, which descendants must implement.
For your immediate problem, you can rename your class_name() functions to class_name_impl() or similar, then in the base class have a class_name() function that calls the implementation one. That way, only the base class version will match when calling class_name() on a derived object.
More generally, you can frustrate attempts to call the base class methods by having same-named functions in the derived classes - as you've done, but anyone can cast to a Base& and call whatever they like. You can't stop virtual methods being overridable in derived classes... you can only frustrate their use.
It's worth remembering that a publicly derived class IS an instance of the base class, and SHOULD provide the base class's interface.
EDIT: re yout "real world example" edit, can you explain the problem with a normal implementation ala...
#include <iostream>
struct Visitor
{
virtual void operator()(int&) const = 0;
};
struct X
{
virtual void visit(Visitor& v) { v(a); v(b); }
int a;
int b;
};
struct X_with_C : X
{
int c;
virtual void visit(Visitor& v) { X::visit(v); v(c); }
};
struct My_Visitor : Visitor
{
void operator()(int& n) const { std::cout << ++n << '\n'; }
};
int main()
{
X x;
x.a = 10;
x.b = 20;
My_Visitor visitor;
x.visit(visitor);
X_with_C xc;
xc.a = -10;
xc.b = -20;
xc.c = -30;
xc.visit(visitor);
X& rx = xc;
rx.visit(visitor);
}
Output:
11
21
-9
-19
-29
-8
-18
-28
hasn't C++11 added final and override?
http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_overrides_and_final
Four years later, let me add that C++11 has introduced keyword final:
class Base final {
This can also be applied on the virtual methods:
class Base{
protected:
virtual void doWork() = 0;
public:
virtual void startWork() final { doWork(); }
};
class Derived: public Base{
protected:
virtual void doWork() override { /* some work */ }
public:
// error: overriding final function ‘virtual void Base::startWork()’
virtual void startWork() override { /* something else */ }
};
Visual Studio 2005 and above implement a keyword "sealed", which is a Microsoft extension to C++. You put it in the declaration of Level1::class_name(). I don't think there is a portable way.
It appears that you're trying to do something in a way that's hard.
Depending on what it is that you're trying to achieve, the following may be a solution.
#include <iostream>
#include <string>
struct Base
{
virtual std::string class_name() const = 0;
};
class Level1
: public Base
{
public:
std::string class_description() const
{
return "class " + class_name();
}
};
class Level2
: public Level1
{
public:
virtual std::string class_name() const
{
return "Level2";
}
};
int main()
{
Level2 lev2;
std::cout << lev2.class_description() << "\n";
}
In the above code I've assumed it's for debugging/tracing or something like that. For id purposes look into typeid (a built-in operator).
Cheers & hth.,