How to embeed class in c++ library with main()? - c++

I have c++ library with code following code structure:
#include <vector>
std::vector<Base*> UserClasses;
int main(int argc,char** argv)
{
Init(argc,argv)
while(true)
{
for(auto* class : UserClasses){
class->start();
}
DoStuff();
for(auto* class : UserClasses){
class->update();
}
DoStuff();
}
Shutdown();
}
Base class is interface class with virtual methods.Like this:
class Base
{
public:
Base();
virtual ~Base();
virtual void start() = 0;
virtual void update() = 0;
};
The user will write his own classes like this:
class MyClass : public Base
{
public:
MyClass ();
~MyClass ();
virtual void start() override
{
//userstaff
};
virtual void update() override
{
//userstaff
};
};
I want to allow user to include my library and headers in his project, write his own child classes and compile project into executable.
But how can my library create instance of user classes?
It doesn't know anything about them.
Is it possible somehow create instance of class within header file and push it to vector?
I saw that it can be done by initializing static variables because it happens before main but I don't understand how to implement it.

As properly mentioned in the comments, do not define main in a library. Also, avoid non-const global variables, since this is a bad thing (tm). Instead, define a function and pass UserClasses to it directly. And it is better to encapsulate all the state you have in a class:
class Main {
public:
Main(int argc, char** argv) {
Init(argc, argv);
}
int run(const std::vector<std::unique_ptr<Base>>& user_classes)
{
while(true)
{
for(const auto& class : user_classes){
class->start();
}
DoStuff();
for(const auto& class : user_classes){
class->update();
}
DoStuff();
}
Shutdown();
}
private:
void DoStuff();
void Shutdown();
// ...
};

it can be done by initializing static variables
Yes, here's an example.
This is similar to #fabian's answer, but:
You don't need to manually register the classes.
The classes are not constructed automatically, you do it when you need them.
run on gcc.godbolt.org
#include <cstddef>
#include <iostream>
#include <memory>
#include <vector>
class BaseLow
{
template <typename T> friend class Base;
using factory_func_t = std::unique_ptr<BaseLow>(*)();
static std::vector<factory_func_t> &GetFactoryFuncsMutable()
{
static std::vector<factory_func_t> ret;
return ret;
}
public:
virtual ~BaseLow() {}
virtual void foo() = 0;
static std::vector<factory_func_t> &GetFactoryFuncs()
{
return GetFactoryFuncsMutable();
}
};
template <typename T>
class Base : public BaseLow
{
static std::nullptr_t RegisterSelf()
{
GetFactoryFuncsMutable().push_back([]() -> std::unique_ptr<BaseLow>
{
return std::make_unique<T>();
});
return nullptr;
}
inline static const std::nullptr_t dummy = RegisterSelf();
// Force `dummy` to be instantiated.
static constexpr std::integral_constant<decltype(&dummy), &dummy> dummy_helper{};
};
struct A : Base<A>
{
void foo() override
{
std::cout << "I'm A!\n";
}
};
struct B : Base<B>
{
void foo() override
{
std::cout << "I'm B!\n";
}
};
int main()
{
std::vector<std::unique_ptr<BaseLow>> objects;
for (const auto &func : BaseLow::GetFactoryFuncs())
objects.push_back(func());
for (auto &obj : objects)
obj->foo();
}

But how can my library create instance of user classes?
You can't but you can provide the user with a convenient way of adding a instance. You could e.g. provide a template class that registers an instance of a class in the constructor which allows the user to add an instance by simply defining an instance of this class.
Example
(Static) Library
Base.h
int main(int, char**);
template<typename T>
class BaseRegistrar
{
public:
BaseRegistrar();
};
class Base
{
public:
Base();
virtual ~Base();
virtual void start() = 0;
virtual void update() = 0;
private:
static std::vector<std::unique_ptr<Base>>& GetBaseInstances();
friend int main(int, char**);
template<typename T>
friend class BaseRegistrar;
};
template<typename T>
BaseRegistrar<T>::BaseRegistrar()
{
Base::GetBaseInstances().emplace_back(new T);
}
Base.cpp
#include "Base.h"
Base::Base(){}
Base::~Base(){}
std::vector<std::unique_ptr<Base>>& Base::GetBaseInstances()
{
static std::vector<std::unique_ptr<Base>> instances;
return instances;
}
main.cpp
#include "Base.h"
int main(int argc,char** argv)
{
for(auto& clazz : Base::GetBaseInstances()){
clazz->start();
}
for(auto& clazz : Base::GetBaseInstances()){
clazz->update();
}
}
Executable
MyClass.cpp
#include "Base.h"
#include <iostream>
class MyClass : public Base
{
public:
MyClass ()
{}
~MyClass ()
{}
virtual void start() override
{
std::cout << "MyClass::start()\n";
}
virtual void update() override
{
std::cout << "MyClass::update()\n";
}
};
// adds an instance of the class to the list
BaseRegistrar<MyClass> registrar;
Output
MyClass::start()
MyClass::update()

Related

C++ workaroud virtual template method

i know there is nothing like virtual template method in C++, but as it seems it is exactly what i need. Is there any workaround i could use? I am thankful for any suggestion.
I would like to add Entities to a vector by a add method, which need to be virtual and also template, how to avoid this?
#include <iostream>
#include <vector>
class EntityBase {
public:
};
class EntityDerived1 : public EntityBase {
public:
};
class EntityDerived2 : public EntityBase {
public:
};
class ContainerBase {
public:
template<typename T>
virtual void add() = 0; // i know this is not allowed!!!
};
class ContainerConcrete : public ContainerBase {
public:
template<typename T>
void add() override { // i know this is not allowed!!!
data.push_back(std::make_shared<T>());
}
void doSecretStuffWithDataHere() {
// ...
}
private:
std::vector<std::shared_ptr<EntityBase>> data;
};
class Engine {
public:
Engine() :
container(std::make_shared<ContainerConcrete>())
{}
ContainerBase& getContainer() {
auto rawPointer = container.get();
return *container;
}
private:
std::shared_ptr<ContainerConcrete> container;
};
int main() {
Engine engine;
ContainerBase& container = engine.getContainer();
container.add<EntityDerived1>();
container.add<EntityDerived2>();
}
Just make add a regular virtual function that takes shared_ptr as a parameter
class ContainerBase {
public:
virtual void add(std::shared_ptr<EntityBase>) = 0;
};
class ContainerConcrete : public ContainerBase {
public:
void add(std::shared_ptr<EntityBase> p) override {
data.push_back(p);
}
// . . .
And then invoke it with make_shared for the desired type:
int main() {
Engine engine;
ContainerBase& container = engine.getContainer();
container.add(std::make_shared<EntityDerived1>());
container.add(std::make_shared<EntityDerived2>());
}
Alternatively you can add a templated overload that invokes make_shared:
virtual void add(std::shared_ptr<EntityBase>) = 0;
template<typename T>
void add() {
add(std::make_shared<T>());
}

Is it possible to have a virtual type in C++?

I have a class MyClass (with several virtual functions) that performs operations on an object called MyType.
The class MyClassImpl inherits MyClass and implements the virtual functions, but I need to add additional members to MyType, but I don't want to modify the class MyType (instead I want to keep it generic).
Now, if I make a MyTypeImpl and inherit MyType, I can add members. But, how do I make the non virtual functions in MyClassImpl (inherited from MyClass) use the new MyTypeImpl?
The only way I can think is to make MyClass use MyTypeImpl but I want to avoid using the implementation in the generic class because I might use various different implementations.
Here is a simple example of what the classes might look like. Of course, the code will not compile because the methods and members added in MyTypeImpl and not MyType.
class MyType {
public:
void increment() {
data_++;
}
protected:
int data_ = 0;
};
class MyClass {
public:
void alg() {
sub_routine_1();
sub_routine_2();
modify_mytype();
};
protected:
MyType mytype_;
virtual void sub_routine_1() = 0;
virtual void sub_routine_2() = 0;
void modify_mytype() {
mytype_.increment();
};
};
class MyTypeImpl : public MyType {
public:
void decrement() {
data_--;
is_decremented = true;
};
protected:
bool is_decremented = false;;
};
class MyClassImpl : public MyClass{
public:
void print() {
mytype_.print();
};
protected:
virtual void sub_routine_1() {
//do algorithm things here
mytype_.increment();
mytype_.increment();
};
virtual void sub_routine_2() {
//do more algorithm things here
mytype_.decrement();
mytype_.decrement();
};
};
After seeing your example I see now that you just want to extend the functionality of that class without modifying the original class. If you need to add additional functions, but you don't want to change the type that is stored in MyClass there isn't any way I know of to make that happen without at least modifying MyType to include virtual functions for the functions you want to call.
You also need to make MyClass take a pointer to MyType so you can use polymorphism and make the calls resolve to the correct implementation:
Dynamic Polymorphism Solution:
#include <iostream>
class MyType {
public:
virtual void increment() {
data_++;
}
// To be implemented by implementation class
virtual void print() = 0;
// To be implemented by implementation class
virtual void decrement() = 0;
protected:
int data_ = 0;
};
class MyTypeImpl : public MyType
{
public:
void print() {
std::cout << 42 << std::endl;
}
void decrement() {
data_--;
is_decremented = true;
};
protected:
bool is_decremented = false;;
};
class MyClass {
public:
MyClass(MyType* mytype)
: mytype_(mytype)
{}
void alg() {
sub_routine_1();
sub_routine_2();
modify_mytype();
};
protected:
MyType* mytype_;
virtual void sub_routine_1() = 0;
virtual void sub_routine_2() = 0;
void modify_mytype() {
mytype_->increment();
};
};
class MyClassImpl : public MyClass{
public:
MyClassImpl(MyType* mytype)
: MyClass(mytype)
{}
void print() {
mytype_->print();
};
protected:
virtual void sub_routine_1() {
//do algorithm things here
mytype_->increment();
mytype_->increment();
};
virtual void sub_routine_2() {
//do more algorithm things here
mytype_->decrement();
mytype_->decrement();
};
};
int main()
{
MyType* mytype = new MyTypeImpl();
MyClass* myclass = new MyClassImpl(mytype);
// Prints "42"
myclass->print();
// Do other stuff with "myclass"
delete myclass;
delete mytype;
}
Note, I am only using a raw pointer in this example for increased clarity. It is highly recommended that you don't use new and delete and use smart pointers to manage the lifetime of your pointers instead.
Static Polymorphism Solution:
Not that the design of this solution is actually any better, but I think this is closer to what you are actually looking for because it doesn't require modifying the MyType class directly. Also the only modification needed for MyClass is to make it a template class:
#include <iostream>
class MyType {
public:
virtual void increment() {
data_++;
}
protected:
int data_ = 0;
};
class MyTypeImpl : public MyType
{
public:
void print() {
std::cout << data_ << std::endl;
}
void decrement() {
data_--;
is_decremented = true;
};
protected:
bool is_decremented = false;
};
template <typename T>
class MyClass {
public:
void alg() {
sub_routine_1();
sub_routine_2();
modify_mytype();
};
protected:
T mytype_;
virtual void sub_routine_1() = 0;
virtual void sub_routine_2() = 0;
void modify_mytype() {
mytype_.increment();
};
};
template <typename T>
class MyClassImpl : public MyClass<T> {
public:
void print() {
this->mytype_.print();
};
protected:
virtual void sub_routine_1() {
//do algorithm things here
this->mytype_.increment();
this->mytype_.increment();
};
virtual void sub_routine_2() {
//do more algorithm things here
this->mytype_.decrement();
this->mytype_.decrement();
};
};
int main()
{
// Use the template to get the correct implementation
MyClassImpl<MyTypeImpl> myclass;
myclass.alg();
myclass.print();
// Do other stuff with my class
}

Is that possible to know all the name of derived classes?

Suppose we have a base class and a bunch of derived classes. Is there any way or mechanism to know all the derived class names programmatically?
Maybe reflection is a good idea, but it's not available on C++. I suppose there will be some kind of template that can finish this job during compilation.
class Base{
public:
virtual void print(){
// This function should print all the names of derived class.
}
virtual Base* getInstance(string class_name){
// This function should return an instance related to the class name.
}
};
class Derived_1 : public Base{ // Suppose we have 100 Derived_X classes,
// so we don't want to add its name to a list manually.
};
int main(){
Base base;
base.print(); // This should print the name of all the derived class.
base.getInstance("Derived_1"); // This should return an instance of Derived_1
return 0;
}
This solution is based on the fact that it seems you are actually looking for a factory. It uses a small macro to ease classes registration, hope you don't care about it.
factory.h
#ifndef __FACTORY_H__
#define __FACTORY_H__
#include <map>
#include <functional>
#include <string>
#include <iostream>
template<class B>
class Factory {
std::map<std::string, std::function<B*()>> s_creators;
public:
static Factory<B>& getInstance() {
static Factory<B> s_instance;
return s_instance;
}
template<class T>
void registerClass(const std::string& name) {
s_creators.insert({name, []() -> B* { return new T(); }});
}
B* create(const std::string& name) {
const auto it = s_creators.find(name);
if (it == s_creators.end()) return nullptr; // not a derived class
return (it->second)();
}
void printRegisteredClasses() {
for (const auto &creator : s_creators) {
std::cout << creator.first << '\n';
}
}
};
#define FACTORY(Class) Factory<Class>::getInstance()
template<class B, class T>
class Creator {
public:
explicit Creator(const std::string& name) {
FACTORY(B).registerClass<T>(name);
}
};
#define REGISTER(base_class, derived_class) \
Creator<base_class, derived_class> s_##derived_class##Creator(#derived_class);
#endif
example.cpp
#include "factory.h"
#include <memory>
class Base {
public:
virtual void printName() const { std::cout << "Base\n"; }
};
class Derived1 : public Base {
public:
virtual void printName() const override { std::cout << "Derived1\n"; }
};
REGISTER(Base, Derived1);
class Derived2 : public Base {
public:
virtual void printName() const override { std::cout << "Derived2\n"; }
};
REGISTER(Base, Derived2);
int main() {
std::cout << "Registered classes:" << std::endl;
FACTORY(Base).printRegisteredClasses();
std::cout << "---" << std::endl;
std::unique_ptr<Base> derived1(FACTORY(Base).create("Derived1"));
derived1->printName();
return 0;
}
Note: requires C++11.
For the getInstance you can declare it a template (needs C++14). To get all the names of the derived classes in the program you probably have to resort to some preprocessor hack.
#include <type_traits>
class Base
{
public:
virtual ~Base () = default;
template < typename T,
typename = std::enable_if_t<std::is_base_of<Base, T>::value, void>
>
T getInstance() { return T{}; }
};
class Derived : public Base {};
class NotDerived {};
int main(){
Base base;
base.getInstance<Derived>();
// error: no matching member function for call to 'getInstance'
//base.getInstance<NotDerived>();
}
Regarding the name of the derived classes, I propose a solution based on a BaseList class/struct, with a static std::set (or other container) of names, a template Base class/struct, that inherit from BaseList and whose template parameter is the derived class (CRTP style) and (to semplify the construction of the derived classes/struct, a C-style macro (I know... macros are distilled evil... but sometimes...) to create the declaration of the derived classes/structs with a necessary static method, that declare the name of the derived class/struct, and a member (that activate the registration of the name).
The following is a full example (unfortunately is a C++11 one)
#include <set>
#include <string>
#include <iostream>
struct BaseList
{
static std::set<std::string> const & derList (std::string const & dn)
{
static std::set<std::string> dl;
if ( dn.size() )
dl.insert(dn);
return dl;
}
static void print ()
{
std::cout << "derived names: ";
for ( auto const & dn : derList("") )
std::cout << dn << ", ";
std::cout << std::endl;
}
};
template <typename Der>
struct Base : public BaseList
{
static std::size_t setNameInList ()
{ return derList(Der::name()).size(); }
static std::size_t id;
};
template <typename Der>
std::size_t Base<Der>::id = setNameInList();
#define setDerived(nameDer) \
struct nameDer : public Base<nameDer>\
{ \
std::size_t idc { id }; \
static std::string name () \
{ return #nameDer; }
setDerived(Derived_1)
// other elements
};
setDerived(Derived_2)
// other elements
};
setDerived(Derived_3)
// other elements
};
int main()
{
BaseList::print();
}
Regarding the getInstance() problem, the only solution that I can imagine is the same solution proposed by Enry Menke (+1), so I suggest that you get the instance through a template type parameter.

How can one design a base class, so it knows about all the "derived" classes, at run time?

Normally, if you know all the types you intend to create before hand, you can just do something like this:
typedef enum{
BASE_CREATURE_TYPE = 0,
ANIMAL_CREATURE_TYPE,
...
}CREATURE_TYPES
But this becomes tedious, because each time you create a new class, you need to update the enum. Also, the CREATURE_TYPES is still just items in an enum - how to tie to an actual class ?
I was wondering if there was some way, I could just write the classes, and at run time, without actually instantiating an object, create a set containing all the types.
Is this possible in C++? In Java there is something called "static blocks", which are executed when the class is loaded by the JVM.
EDIT: This question is not about static blocks - It is just an example - I am wondering if there is some way, that I can execute a method or block of code so I know what classes exist at runtime, without actually creating an object
EDIT: I meant set of all types, not "maps", so I can create an object of each type, without having to maintain a list.
EDIT: The reason I want this, is because I am trying to create a function that can call methods on all derived classes that are part of the application. For example, say I have several classes which all derive from class Foo, and have a balls():
Foo{
balls();
}
Boo : public Foo{
balls();
}
Coo: public Foo{
balls():
}
At run time, I would like to know about all the derived classes so I can call:
DerivedClass:balls();
EDIT: Note, that I do not need to know about all the members of each derived class, I just want to know what all the derived classes are, so I can call balls(), on each of them.
EDIT: This question is similar: How to automatically register a class on creation
But unfortunately, he is storing an std::string(). How does one refer to the actual class ?
EDIT: In Smeehey's answer below, in the main method, how would I actually create an instance of each class, and call both static and non-static methods ?
You could create a static registry for all your classes, and use a couple of helper macros to register new types within it. Below is a basic working demonstration, which creates 2 derived classes from Base. To add new classes you just use the two macros shown - one inside and one outside the class. Note: the example is very bare-bones and doesn't concern itself with things like checking for duplicates or other error conditions to maximise clarity.
class BaseClass
{
};
class Registry
{
public:
static void registerClass(const std::string& name, BaseClass* prototype)
{
registry[name] = prototype;
}
static const std::map<std::string, BaseClass*>& getRegistry() { return registry; };
private:
static std::map<std::string, BaseClass*> registry;
};
std::map<std::string, BaseClass*> Registry::registry;
#define REGISTER_CLASS(ClassType) static int initProtoType() { static ClassType proto; Registry::registerClass(std::string(#ClassType), &proto); return 0; } static const int regToken;
#define DEFINE_REG_CLASS(ClassType) const int ClassType::regToken = ClassType::initProtoType();
class Instance : public BaseClass
{
REGISTER_CLASS(Instance)
};
DEFINE_REG_CLASS(Instance)
class OtherInstance : public BaseClass
{
REGISTER_CLASS(OtherInstance)
};
DEFINE_REG_CLASS(OtherInstance)
int main()
{
for(auto entry : Registry::getRegistry())
{
std::cout << entry.first << std::endl;
}
return 0;
}
The above registers prototypes of the derived classes, which could be used for copy-constructing other instances for example. As an alternative, requested by the OP, you can have a system where factory methods are registered instead of prototypes. This allows you to create instances using a constructor with any particular signature, rather than the copy constructor:
class BaseClass
{
};
class Registry
{
public:
using factoryMethod = BaseClass* (*)(int a, int b, int c);
static void registerClass(const std::string& name, factoryMethod meth)
{
registry[name] = meth;
}
static BaseClass* createInstance(const std::string& type, int a, int b, int c)
{
return registry[type](a, b, c);
}
static const std::map<std::string, factoryMethod>& getRegistry() { return registry; };
private:
static std::map<std::string, factoryMethod> registry;
};
std::map<std::string, Registry::factoryMethod> Registry::registry;
#define REGISTER_CLASS(ClassType) static BaseClass* createInstance(int a, int b, int c) \
{ \
return new ClassType(a,b,c); \
} \
static int initRegistry() \
{ \
Registry::registerClass( \
std::string(#ClassType), \
ClassType::createInstance); \
return 0; \
} \
static const int regToken; \
#define DEFINE_REG_CLASS(ClassType) const int ClassType::regToken = ClassType::initRegistry();
class Instance : public BaseClass
{
Instance(int a, int b, int c){}
REGISTER_CLASS(Instance)
};
DEFINE_REG_CLASS(Instance)
class OtherInstance : public BaseClass
{
OtherInstance(int a, int b, int c){}
REGISTER_CLASS(OtherInstance)
};
DEFINE_REG_CLASS(OtherInstance)
int main()
{
std::vector<BaseClass*> objects;
for(auto entry : Registry::getRegistry())
{
std::cout << entry.first << std::endl;
objects.push_back(Registry::createInstance(entry.first, 1, 2, 3));
}
return 0;
}
Use the CRTP design with interface for common "ancestor":
#include <vector>
#include <iostream>
/* Base */
struct IBase
{
virtual void balls() = 0;
virtual IBase *clone() const = 0;
private:
static std::vector<IBase const *> _Derived;
public:
static void
create_all(void)
{
std::cout << "size: " << _Derived.size() << "\n";
for (IBase const *a : _Derived)
{
IBase *new_object(a->clone());
(void)new_object; // do something with it
}
}
};
std::vector<IBase const *> IBase::_Derived;
/* Template for CRTP */
template<class DERIVED>
class Base : public IBase
{
static bool created;
static Base const *_model;
public:
Base(void)
{
if (not created)
{
_Derived.push_back(this);
created = true;
}
}
};
template<class DERIVED>
bool Base<DERIVED>::created = false;
template<class DERIVED>
Base<DERIVED> const *Base<DERIVED>::_model = new DERIVED;
/* Specialized classes */
struct Foo1 : public Base<Foo1>
{
IBase *clone() const
{
std::cout << "new Foo1\n";
return new Foo1(*this);
}
void balls() {}
};
struct Foo2 : public Base<Foo2>
{
IBase *clone() const
{
std::cout << "new Foo2\n";
return new Foo2(*this);
}
void balls() {}
};
int main(void)
{
Foo1 a;
IBase::create_all();
}
I tried this solution, but I do not know why the static Base const *_model; is not created when running the program.
You may use a global factory holding functions able to create objects (unique_ptr's) of derived classes:
#include <memory>
#include <unordered_map>
#include <typeinfo>
#include <typeindex>
// Factory
// =======
template <typename Base>
class Factory
{
public:
template <typename Derived>
struct Initializer {
Initializer() {
Factory::instance().register_producer<Derived>();
}
};
typedef std::function<std::unique_ptr<Base>()> producer_function;
typedef std::unordered_map<std::type_index, producer_function> producer_functions;
static Factory& instance();
void register_producer(const std::type_info& type, producer_function producer) {
m_producers[std::type_index(type)] = std::move(producer);
}
template <typename Derived>
void register_producer() {
register_producer(
typeid(Derived),
[] () { return std::make_unique<Derived>(); });
}
producer_function producer(const std::type_info& type) const {
auto kv = m_producers.find(std::type_index(type));
if(kv != m_producers.end())
return kv->second;
return producer_function();
}
const producer_functions producers() const { return m_producers; }
private:
producer_functions m_producers;
};
template <typename Base>
Factory<Base>& Factory<Base>::instance() {
static Factory result;
return result;
}
// Test
// ====
#include <iostream>
class Base
{
public:
~Base() {}
virtual void print() = 0;
};
class A : public Base
{
public:
void print() override { std::cout << "A\n"; }
static void f() {}
};
Factory<Base>::Initializer<A> A_initializer;
class B : public Base
{
public:
void print() override { std::cout << "B\n"; }
};
Factory<Base>::Initializer<B> B_initializer;
class C {};
int main()
{
auto& factory = Factory<Base>::instance();
// unique_ptr
auto producerA = factory.producer(typeid(A));
if(producerA) {
auto ptrA = producerA();
ptrA->print();
}
// shared_ptr
auto producerB = factory.producer(typeid(B));
if(producerB) {
std::shared_ptr<Base> ptrB(producerB());
ptrB->print();
}
// missing
auto producerC = factory.producer(typeid(C));
if( ! producerC) {
std::cout << "No producer for C\n";
}
// unordered
for(const auto& kv : factory.producers()) {
kv.second()->print();
}
}
Note: The factory does not provide means of calling static member functions without object.

callback function design C++

I'm trying to implement a callback manager that can register and execute the callbacks from different classes, which each classes are from a different DLL.
Each of these classes derives from a common base class. I know how a single class can make use of a template class like below to register and call its own function, but how can this be applied to use on multiple classes sharing the same callback manager?
Any help will be greatly appreciated.
file: callbacktemplate.h
------------------------
#include <functional>
#include <string>
template <class cInstance>
class cCallBackManager
{
private:
typedef void (cInstance::*tFunction)();
typedef std::map<std::string, tFunction> funcMap;
funcMap i_funcMap;
public:
void SetFunPointer(std::string funcName, tFunction function)
{
i_funcMap.insert(std::pair<std::string, tFunction>(funcName, function));
}
void GetFunPointer(cInstance& obj) //how to call this without knowing the type?
{
for (funcMap::iterator it = i_funcMap.begin();it!=i_funcMap.end(); ++it)
{
(obj.*(it->second))();
}
}
};
file:example.h
---------------
#include "callbacktemplate.h"
class A: public base
{
private:
cCallBackManager<A> callback;
public:
A()
{
callback.SetFunPointer<A>("eventA", &A::testcallback);
callback.GetFunPointer(&this); //how to generalize this so this can be called from the callback manager with the class object?
};
~A(){};
void testCallback();
};
class B: public base
{
private:
cCallBackManager<B> callback;
public:
B()
{
callback.SetFunPointer<B>("eventB", &B::testcallback);
};
~B(){};
void testCallback();
};
file: main.cpp
------------------
#include "derived.h"
int main()
{
A a;
B b;
//create a callback manager to execute the callback?
callbackmgr.execute() //execute all the callback
return 0;
}
lf not using templatized callback manager, how can i achieve something like SetFunPointer(EVENT_NAME, (Base Class)A::testCallback)?
Thanks guys. I've managed to come up with something with your "pointers". :)
File: cCallBackInterface.h
template<class cClass>
class cCallBackInterface
{
public:
cCallBackInterface(){};
~cCallBackInterface(){};
typedef void (cClass::*Function)();
cCallBackInterface(cClass* obj, Function _Function)
{
cInstance = obj;
m_Function = _Function;
}
void execute()
{
(cInstance->*m_Function)();
}
private:
cClass* cInstance;
Function m_Function;
};
File: base.h
class BaseModel;
typedef cCallBackInterface<BaseModel> CallBackInterface;
typedef void(BaseModel::*basefn)();
class BaseModel
{
public:
BaseModel(){};
~BaseModel(){};
}
};
class derived : public BaseModel
{
public:
derived(){};
~derived(){};
void dosomething()
{
cout << "derived class is doing something." << endl;
}
};
File: main.cpp
int main()
{
derived a;
std::vector<CallBackInterface> callback;
callback.push_back(CallBackInterface(&a, (basefn)(&derived::Adosomething)));
for(int i = 0; i < callback.size(); i++)
callback[i].execute();
return 0;
}
You can look at this question regarding using member-function pointers.
What it boils down to is that you need the instance as well as the mem-func pointer, you cannot have a generic one to be used anywhere.