In a project I am working in, I need to be able to access the full class name of each and every instance in the program. My approach was declaring a base class from which all the classes would derive and which would have a method that would return the name of the class of the given instance properly demangled. That would look like as follows :
class Base {
public:
std::string *getClassName() {
char *str = (char*) malloc(1024);
size_t size = 1024;
int status;
char *res = abi::__cxa_demangle( typeid(*this).name(), str, &size, &status );
return new std::string(res);
};
class A : public Base { /*...*/ };
class B : public A { /*...*/ };
// ... and so on
The problem is that when I access getClassName from, say, an instance of class B, it returns not Base::A::B but just Base, which is the class that is visible from the place where getClassName is declared.
The only solution I found is to make getClassName virtual and force every class to implement it. But that means rewriting always the same code, which I do not want. Do you know any elegant solution to this?
You can just define virtual destructor in Base class:
#include <iostream>
#include <malloc.h>
#include <cxxabi.h>
using namespace std;
class Base {
public:
virtual ~Base() {}
std::string getClassName() {
char *str = (char*) malloc(1024);
size_t size = 1024;
int status;
char *res = abi::__cxa_demangle( typeid(*this).name(), str, &size, &status );
return std::string(res);
}
};
class A : public Base { /*...*/ };
class B : public A { /*...*/ };
int main()
{
A a;
B b;
cout << a.getClassName() << endl;
cout << b.getClassName() << endl;
}
Output:
./test
A
B
BTW in this case it's better let __cxa_demangle to allocate memory (and don't forget to ::free() it because this example code has memory leak)
Make your Base class a template on the derived class and pass to the constructor the derived class's this pointer. Something like:
template <DerivedT> class Base {
DerivedT * self;
public:
Base(DerivedT * s) : self(s) {}
// ....
};
Then call typeid on *self rather than *this.
Your derived classes will have to become:
template <DerivedT> class A : public Base<DerivedT> { /*...*/ };
class B : public A<B> { /*...*/ };
And pass this up along the constructor chain.
Have a variable that is protected in Class Base, and set the value of it in every derived class, and in getClassName return the same variable..
class Base{
protected:
std:string* _pstrClassName;
}
class A{
A():_pstrClassName("A"){
}
}
Related
I have a base class B with derived classes X, Y and Z (in fact, more than 20 derived classes). Each class has a tag() function that identifies which (derived) class it is. My program stores instances of the derived classes as pointers in a vector defined as vector<B*>. Each derived class may appear in this vector 0..n times.
I would like to have a function that looks through the vector for instances of a derived type and returns a new vector with the type of the derived class, eg
#include <vector>
using namespace std;
class B {
public:
// ...
virtual int tag() {return 0xFF;};
};
class X : public B {
// ...
int tag() {return 1;};
vector<X*> find_derived(vector<B*> base_vec) {
vector<X*> derived_vec;
for (auto p : base_vec) {
if (p->tag() == tag()) {
derived_vec.push_back((X*) p);
}
}
return derived_vec;
}
};
Obviously I don't want to have to define find_derived in each derived class but I don't see how to do this as a virtual function. Currently I am doing it using a macro but, since I am learning C++, I woudl prefer a method that used language constructs rather than those in the pre-processor. Is there another way?
One possibility:
template <typename D>
class FindDerivedMixin {
public:
vector<D*> find_derived(const vector<B*>& base_vec) {
int my_tag = static_cast<D*>(this)->tag();
vector<D*> derived_vec;
for (auto p : base_vec) {
if (p->tag() == my_tag) derived_vec.push_back(static_cast<D*>(p));
}
return derived_vec;
}
};
class X : public B, public FindDerivedMixin<X> {};
Like the previous answer, what you need is some template programming.
This is an example without mixin though:
#include <vector>
#include <iostream>
#include <type_traits>
#include <string>
//-----------------------------------------------------------------------------
// Base class
class Base
{
public:
virtual ~Base() = default;
// pure virtual method to be implemented by derived classes
virtual void Hello() const = 0;
protected:
// example of a constuctor with parameters
// it is protected since no instances of Base
// should be made by accident.
explicit Base(const std::string& message) :
m_message(message)
{
}
// getter for private member variable
const std::string& message() const
{
return m_message;
}
private:
std::string m_message;
};
//-----------------------------------------------------------------------------
// Class which contains a collection of derived classes of base
class Collection
{
public:
Collection() = default;
virtual ~Collection() = default;
// Add derived classes to the collection.
// Forward any arguments to the constructor of the derived class
template<typename type_t, typename... args_t>
void Add(args_t&&... args)
{
// compile time check if user adds a class that's derived from base.
static_assert(std::is_base_of_v<Base, type_t>,"You must add a class derived from Base");
// for polymorphism to work (casting) we need pointers to derived classes.
// use unique pointers to ensure it is the collection that will be the owner of the
// instances
m_collection.push_back(std::make_unique<type_t>(std::forward<args_t>(args)...));
}
// Getter function to get derived objects of type_t
template<typename type_t>
std::vector<type_t*> get_objects()
{
static_assert(std::is_base_of_v<Base, type_t>, "You must add a class derived from Base");
// return non-owning pointers to the derived classes
std::vector<type_t*> retval;
// loop over all objects in the collection of type std::unique_ptr<Base>
for (auto& ptr : m_collection)
{
// try to cast to a pointer to derived class of type_t
type_t* derived_ptr = dynamic_cast<type_t*>(ptr.get());
// if cast was succesful we have a pointer to the derived type
if (derived_ptr != nullptr)
{
// add the non-owning pointer to the vector that's going to be returned
retval.push_back(derived_ptr);
}
}
return retval;
}
private:
std::vector<std::unique_ptr<Base>> m_collection;
};
//-----------------------------------------------------------------------------
// some derived classes for testing.
class Derived1 :
public Base
{
public:
explicit Derived1(const std::string& message) :
Base(message)
{
}
virtual ~Derived1() = default;
void Hello() const override
{
std::cout << "Derived1 : " << message() << "\n";
}
};
//-----------------------------------------------------------------------------
class Derived2 :
public Base
{
public:
explicit Derived2(const std::string& message) :
Base(message)
{
}
virtual ~Derived2() = default;
void Hello() const override
{
std::cout << "Derived2 : " << message() << "\n";
}
};
//-----------------------------------------------------------------------------
int main()
{
Collection collection;
collection.Add<Derived1>("Instance 1");
collection.Add<Derived1>("Instance 2");
collection.Add<Derived2>("Instance 1");
collection.Add<Derived2>("Instance 2");
collection.Add<Derived1>("Instance 3");
// This is where template programming really helps
// the lines above where just to get the collection filled
auto objects = collection.get_objects<Derived1>();
for (auto& derived : objects)
{
derived->Hello();
}
return 0;
}
TL;DR
I am trying to pass a subclass into a function that expects the subclass's base class and then store a unique pointer of that base class in a vector in a third, completely separate class.
(C++ 11 and higher)
End TL;DR
I have 3 classes total and then my int main().
The base (abstract) class has a constructor and a virtual function.
The base class constructor is implemented, the virtual function is not.
The second class is the subclass to the base class.
It implements its own constructor and calls the base constructor.
The second part of the sub class is the concrete implementation of the virtual base class function.
I then have a third class that has its own constructor.
This third class has a function whose function header contains a reference to the base class.
This same function then tries to pass this reference to the abstract class and then .push_back() the reference into a vector of std::unique_ptr of this abstract class.
(Because I cannot directly have a vector of abstract class instances.)
My issue is that I am currently unable to get a version of this code to compile.
I have been referencing some resources online to try to solve my problem.
pass unique_ptr as an object
https://stackoverflow.com/questions/8114276/how-do-i-pass-a-unique-ptr-argument-to-a-constructor-or-a-function
adding elements of a vector of a base class
https://stackoverflow.com/questions/31410858/adding-elements-to-stdvector-of-an-abstract-class
can't access derived class method from pointer of base class - not entirely relavent, but good knowledge
https://stackoverflow.com/questions/23489554/cant-access-derived-class-method-from-pointer-of-type-base-class
I have created a shortened version of this problem in an example C++ executable that does not compile.
Here is the file:
/*
This script demonstrates my dilemma of trying to pass a subclass object
as a parameter to a function that expects the base class, and then
take that passed in object in the function and add it to a vector of that object
in a completely different class.
*/
#include <iostream>
#include <memory>
#include <vector>
class Baseclass
{
public:
Baseclass(int i)
{
lala = i;
}
// subclass MUST implement this method.
virtual int addme(int d) = 0;
protected:
int lala;
};
class Subclass : Baseclass
{
public:
Subclass(int d, int l) : Baseclass(d)
{
blahblah = l;
}
int addme(int d)
{
return blahblah + lala + d;
}
protected:
int blahblah;
};
class Mainclass
{
public:
Mainclass(uint blah)
{
anotherone = blah;
}
// This is the function I cannot seem to get to work.
// How can I make the function parameter an abstract class?
// The object being passed in is NOT abstract...
bool addController(Baseclass & basecont)
{
// This line here does NOT compile!!
// controllers.push_back(std::make_unique<What goes here?>(basecont));
return true;
}
protected:
uint anotherone;
std::vector<std::unique_ptr<Baseclass>> controllers;
};
int main(int argc , char ** argv)
{
// create subclassed controllers
Subclass cont1 = Subclass(12, 23);
Subclass cont2 = Subclass(233, 2);
// create main object
Mainclass mainbro = Mainclass(23);
// Add the subclased controllers to the main class
// THESE 2 lines do not compile!!
// mainbro.addController(cont1);
// mainbro.addController(cont2);
//
return 0;
}
I figure that I am doing something very wrong, but I do not feel the process I outlined in itself is impossible. I just think that I am going about the problem wrong.
I have highlighted, in the script, where I am not sure what I should do and where the code breaks.
I may need to take an alternative approach to the problem, I just do not know what alternatives I have available.
I see different way to fix your code, with different meaning.
Store pointers (main has ownership of the objects)
class Mainclass
{
public:
void addController(Baseclass& basecont)
{
controllers.push_back(&basecont);
}
protected:
std::vector<Baseclass*> controllers;
};
Transfer ownership
class Mainclass
{
public:
void addController(std::unique_ptr<Baseclass> basecont)
{
controllers.push_back(std::move(basecont));
}
protected:
std::vector<std::unique_ptr<Baseclass>> controllers;
};
with main:
int main()
{
auto cont1 = std::make_unique<Subclass>(12, 23);
auto cont2 = std::make_unique<Subclass>(233, 2);
Mainclass mainbro(23);
mainbro.addController(std::move(cont1));
mainbro.addController(std::move(cont2));
}
Store copies
class Mainclass
{
public:
void addController(Baseclass& basecont)
{
controllers.push_back(basecont.clone());
}
protected:
std::vector<std::unique_ptr<Baseclass>> controllers;
};
With
class Baseclass
{
// ...
public:
virtual int addme(int d) = 0;
virtual std::unique_ptr<Baseclass> clone() = 0;
};
class Subclass : Baseclass
{
// ...
public:
std::unique_ptr<Baseclass> clone() override { return std::make_unique<Subclass>(*this); }
};
Whenever you use base pointers or references with virtual methods, always add a virtual destructor:
virtual ~Baseclass() = default;
This prevents undefined behavior when the base pointers get deleted.
Next bit, use public inheritance to allow the compiler to implicitly upcast from unique_ptr<Subclass> to unique_ptr<Baseclass>:
class Subclass : public Baseclass
Your last issue is one of ownership. By having a vector of unique_ptr, you are saying that your class owns all those objects. But by declaring them on the stack in main you are saying that main owns them. Instead, use make_unique in the main routine, and transfer ownership with std::move:
bool addController(std::unique_ptr<Baseclass> basecont)
{
controllers.push_back(std::move(basecont));
return true;
}
...
auto cont1 = std::make_unique<Subclass>(12, 23);
auto cont2 = std::make_unique<Subclass>(233, 2);
// create main object
Mainclass mainbro = Mainclass(23);
mainbro.addController(std::move(cont1));
mainbro.addController(std::move(cont2));
All together:
#include <iostream>
#include <memory>
#include <vector>
class Baseclass
{
public:
Baseclass(int i)
{
lala = i;
}
virtual ~Baseclass() = default;
// subclass MUST implement this method.
virtual int addme(int d) = 0;
protected:
int lala;
};
class Subclass : public Baseclass
{
public:
Subclass(int d, int l) : Baseclass(d)
{
blahblah = l;
}
int addme(int d)
{
return blahblah + lala + d;
}
protected:
int blahblah;
};
class Mainclass
{
public:
Mainclass(uint blah)
{
anotherone = blah;
}
bool addController(std::unique_ptr<Baseclass> basecont)
{
controllers.push_back(std::move(basecont));
return true;
}
protected:
uint anotherone;
std::vector<std::unique_ptr<Baseclass>> controllers;
};
int main(int argc , char ** argv)
{
// create subclassed controllers
auto cont1 = std::make_unique<Subclass>(12, 23);
auto cont2 = std::make_unique<Subclass>(233, 2);
// create main object
Mainclass mainbro = Mainclass(23);
mainbro.addController(std::move(cont1));
mainbro.addController(std::move(cont2));
return 0;
}
Demo: https://godbolt.org/z/EyQD6S
#include <iostream>
#include <memory>
#include <vector>
class Baseclass
{
public:
Baseclass(int i)
{
lala = i;
}
// subclass MUST implement this method.
virtual int addme(int d) = 0;
protected:
int lala;
};
class Subclass : public Baseclass
{
public:
Subclass(int d, int l) : Baseclass(d)
{
blahblah = l;
}
int addme(int d)
{
return blahblah + lala + d;
}
protected:
int blahblah;
};
class Mainclass
{
public:
Mainclass(uint blah)
{
anotherone = blah;
}
// you need to make the function a template, otherwise
// you'll slice the top off the SubClass, and incorrectly
// make a copy of the base class (which you can't do,
// because BaseClass is pure virtual)
template<typename T>
bool addController(T& basecont)
{
// dont push_back new unique_ptrs, emplace_back instead!
controllers.emplace_back(new T(basecont));
return true;
}
protected:
uint anotherone;
std::vector<std::unique_ptr<Baseclass>> controllers;
};
int main(int argc , char ** argv)
{
// create subclassed controllers
Subclass cont1 = Subclass(12, 23);
Subclass cont2 = Subclass(233, 2);
// create main object
Mainclass mainbro = Mainclass(23);
// It's worth pointing out that these methods will take new copies of
// cont1 and cont2 (we don't want the mainbro instance to delete the
// memory for cont1 and cont2, since they are stack allocated)
mainbro.addController(cont1);
mainbro.addController(cont2);
//
return 0;
}
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.
I haven't worked with derived classes and polymorphism in a while, and I can't figure out how to access a derived class data item.
// Quick example
class Base {
string data1; // data1 = "FOO"
};
class ChildA : public Base {
string data2;
};
int main() {
Base **list;
list = new Base*[1];
base[0] = new ChildA(// data2 = "BAR");
std::cout << base[0]->data1; // FOO
std::cout << base[0]->data2; // Error; no member named "data2" in Base
Is it possible to retrieve the derived data from the base class array?
When you're looking at an instance of a derived class through a pointer to the base class, you can only see the members of the base class, because generally, you wouldn't know what subtype instance you are looking at. The point of polymorphism and virtual functions is that in many cases, you can work with subtype instances without knowing their actual type. For instance, if you want to print information about an instance, and you want data2 to be included when you print a ChildA, you would create a virtual toString() function in Base and override it in ChildA to include data2. Then, you can call toString() without knowing the actual type, and if your instance is actually a ChildA, you'll get data2.
class member variable by default is private.
by using base class pointer, you can not get derived class member var at all.
If you would like to do so, you may want to implement virtual getter function, it will help you getting private member function from derived class.
If the base class interface must have knowledge of data potentially held in a derived class, here is one of the few ways that is not horribly dangerous.
#include <iostream>
#include <vector>
#include <utility>
#include <memory>
#include <stdexcept>
using namespace std;
class Base {
public:
Base(std::string d1 = {"FOO"} ) : _data1 { std::move(d1) } {}
virtual ~Base() = default; // because polymorphism without a virtual base class is naughty
const string& data1() const { return _data1; }
virtual bool has_data2() const { return false; }
virtual const string& data2() const {
throw invalid_argument {"I don't have data2"};
};
private:
string _data1; // data1 = "FOO"
};
class ChildA : public Base {
public:
ChildA(std::string d2, std::string d1 = {"FOO"})
: Base { std::move(d1) }
, _data2 { std::move(d2) }
{}
bool has_data2() const override { return true; }
const std::string& data2() const override {
return _data2;
};
private:
string _data2;
};
int main()
{
vector<unique_ptr<Base>> bases;
bases.push_back(unique_ptr<Base>(new ChildA("bob")));
bases.push_back(unique_ptr<Base>(new Base("not foo")));
for(const auto& p : bases) {
cout << p->data1() << ", " << (p->has_data2() ? p->data2() : "no data 2") << endl;
}
return 0;
}
Basically I have a class let's say Parameter that has a get and set variable.
I also have a base class let's say Vehicle that has a method registerParameter(...) that takes a pointer to function member as getter and a pointer to function member as setter. This method is then supposed to write those two pointers into an object of the parameter class and throws this object into a vector.
And last but not least we have a derived class let's say Car and we call registerParameter(...) with the string "color" as parameter name and a getter and setter from this derived class.
Example in code:
Parameter file
#ifndef BASE_H
#define BASE_H
#include "base.h"
class Parameter
{
std::string (Base::*get)();
void (Base::*set)(std::string);
};
#endif
Base file
#ifndef PARAMETER_H
#define PARAMETER_H
#include <vector>
#include "parameter.h"
class Base
{
public:
std::vector<Parameter> list;
void registerNew(std::string (Base::*get)(), void (Base::*set)(std::string))
{
Parameters parameter;
parameter.get = get;
parameter.set = set;
list.push_back(parameter);
}
};
#endif
Derived file
class Derived
{
public:
Derived derived()
{
registerNew(&getColor, &setColor);
}
std::string getColor()
{
return this->color;
}
std::string setColor(std::string newColor)
{
this->color = newColor;
}
private:
std::string color;
};
I've been thinking about this for days now and I really need the solution until friday evening.
You cannot do what are trying:
The types std::string (Base::*)() and std::string (Derived::*)() are very different. std::string (Derived::*)() cannot be auto converted to std::string (Base::*)().
Take the following scenario.
struct Base
{
int foo() { return 10; }
};
struct Derived : Base
{
int bar() { return 20; }
};
int main()
{
Base base;
int (Base::*bf)() = &Base::foo;
(base.*bf)(); // Should be able to call Base:foo(). No problem.
bf = &Derived::bar; // This is a compiler error. However, if this were allowed....
(base.*bf)(); // Call Derived::bar()?? That will be a problem. base is not an
// instance of Derived.
}
Update
You can do something like:
#include <string>
#include <vector>
class Base;
// Create a base class Functor that provides the interface to be used by
// Base.
struct Functor
{
virtual ~Functor() {}
virtual std::string get(Base& base) = 0;
virtual void set(Base& base, std::string) = 0;
};
// Create a class template that implements the Functor interface.
template <typename Derived> struct FunctorTemplate : public Functor
{
// typedefs for get and set functions to be used by this class.
typedef std::string (Derived::*GetFunction)();
typedef void (Derived::*SetFunction)(std::string);
// The constructor that uses the get and set functions of the derived
// class to do itw work.
FunctorTemplate(GetFunction get, SetFunction set) : get_(get), set_(set) {}
virtual ~FunctorTemplate() {}
// Implement the get() function.
virtual std::string get(Base& base)
{
return (reinterpret_cast<Derived&>(base).*get_)();
}
// Implement the set() function.
virtual void set(Base& base, std::string s)
{
(reinterpret_cast<Derived&>(base).*set_)(s);
}
GetFunction get_;
SetFunction set_;
};
class Base
{
public:
std::vector<Functor*> functorList;
void registerFunctor(Functor* functor)
{
functorList.push_back(functor);
}
};
class Derived : public Base
{
public:
Derived()
{
// Register a FunctorTemplate.
registerFunctor(new FunctorTemplate<Derived>(&Derived::getColor,
&Derived::setColor));
}
std::string getColor()
{
return this->color;
}
void setColor(std::string newColor)
{
this->color = newColor;
}
private:
std::string color;
};
Your base class should know the derived class. That sounds complex but the problem has been solved already:
template<typename DERIVED> class Base
{
public:
class Parameter {
std::string (DERIVED::*get)();
void (DERIVED::*set)();
};
private:
std::list<Parameter> list;
// ...
};
class Derived : public Base<Derived> // !!!
{
registerNew(&Derived::getColor, &Derived::setColor);
};
This solution is known as the Curiously Recurring Template Pattern (CRTP).