The call that generates the unresolved external symbol:
#include <string.h>
#include "GContext.h"
#include "GBitmap.h"
#include "GColor.h"
int main(int argc, char** argv) {
const int W = 100;
const int H = 100;
GContext* ctx = GContext::Create(W, H);
The abstract class method signature:
#ifndef GContext_DEFINED
#define GContext_DEFINED
#include "GTypes.h"
class GBitmap;
class GColor;
class GContext {
public:
GContext() {}
virtual ~GContext() {}
virtual void getBitmap(GBitmap*) const = 0;
virtual void clear(const GColor&) = 0;
static GContext* Create(const GBitmap&);
static GContext* Create(int width, int height);
};
#endif
And the Current Derived Class Implementation and Method Signature:
#include "GColor.h"
#include "GPixel.h"
#include "GBitmap.h"
#include "GContext.h"
#include "GTypes.h"
class myGContext : public GContext
{
public:
myGContext() : GContext(){}
static const GBitmap* bitmap;
void getBitmap(GBitmap* bitmap) const
{
}
void clear(const GColor& gcolor)
{
int length = sizeof( (GPixel)(bitmap->fPixels) ) / sizeof(GPixel);
for (int i = 0; i < length; i++)
{
(bitmap->fPixels)[i]
}
}
static GContext* Create(const GBitmap& gbitmap)
{
GContext::Create(gbitmap);
bitmap = &gbitmap;
GContext* g = new myGContext();
return g;
}
static GContext* Create(int width, int height)
{
GContext::Create(width,height);
GContext* g = new myGContext();
return g;
}
};
So I understand that I need to define both types of the function GContext::Create() to resolve the external symbol error, but I need to define them in my derived Class. Which I thought I was doing right, any ideas?
no Inheritance does not work, this is not like a virtual function.
I'm not exactly sure what you're trying to do but if you
Need to have static functions
Need both base and derived classes to have their own implementation
derived needs access to the base class' functions
this is all achievable:
#include <iostream>
class A {
public:
A() {}
static void f() { std::cout << "A f" << std::endl; }
};
class B : public A {
public:
B() {}
static void f() { std::cout << "B f" << std::endl; }
};
int main(int argc, char* argv[]) {
A a;
B b;
a.f();
b.f();
b.A::f();
return 0;
}
Output is
A f
B f
A f
I think it is just because you static method is not defined in your base class. From here it is said that LNK2019 can also occur when a static data member is declared but not defined.
Also, be careful when you try to redefine static methods inside subclasses:
You cannot override a static method in a subclass, you can only hide it.
And from the C++ standard:
9.4.1 Static member functions [class.static.mfct]
2/ A static member function shall not be virtual. There shall not be a static and a non-static member function with the same name and the same parameter types (13.1). A static member function shall not be declared const, volatile, or const volatile.
Example:
#include <iostream>
class Foo
{
public:
static void func() { std::cout << "Foo::func" << std::endl; }
};
class Bar : public Foo
{
public:
static void func() { std::cout << "Bar::func" << std::endl; }
};
int main(void)
{
Foo::func(); // Works
Bar::func(); // Works
Foo foo;
Bar bar;
foo.func(); // Works
bar.func(); // Works
bar.Foo::func(); // Works
Foo* foobar = new Bar;
foobar->func(); // Not the result expected
// Because no override.
return 0;
}
Related
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()
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.
My scenario is simplified in the following example:
#include <iostream>
#include <vector>
using namespace std;
class C;
class A
{
protected:
C * cPointer;
A();
virtual void updateList() = 0;
void callFunc();
};
class B : public A
{
private:
vector<int> list;
void updateList();
public:
void callFromA();
};
class C
{
friend class A;
friend class B; // I want to get rid off this declaration
private:
int sum;
void set_sum( int val );
public:
static C * getCPointer();
};
A::A()
{
cPointer = C::getCPointer();
}
void A::callFunc()
{
updateList();
}
void B::updateList()
{
list.push_back(2);
list.push_back(4);
int s = 0;
for( unsigned int i=0; i<list.size(); i++ )
{
s += list[i];
}
cPointer->set_sum(s);
}
void B::callFromA()
{
callFunc();
}
void C::set_sum( int val )
{
sum = val;
cout << "Sum at C is: " << sum << endl;
}
C * C::getCPointer()
{
static C cPointer;
return & cPointer;
}
int main( int argc, char ** argv)
{
B b;
b.callFromA();
return 0;
}
This example works fine. But I want to get rid of the "friend class B" declaration in class C and achieving similar functionality. Actually I want to have either of the following:
accessibility of C::set_sum() from B::updateList() which will not be possible without the "friend class B" declaration in class C.
accessibility of B::list in A::callFunc() whereby I can push the logic from B::updateList to A::callFunc() which basically means ability to access a list in the derived class from the base class. In this way, I will be able to access the set_sum() in A::callFunc() due to "friend class A" declaration in class C.
Any idea to achieve this without involving major design changes is desirable!
Thanks!
I'm not sure if I understand all your restrictions, but maybe this works better for you. Basically, you can access B::list from A using a virtual function. I've commented the changes in the code.
#include <iostream>
#include <vector>
using namespace std;
class A;
class C
{
friend class A;
private:
int sum;
void set_sum(int val);
public:
static C * getCPointer();
};
class A
{
protected:
C * cPointer;
A();
virtual int getS() = 0; // virtual function to calculate data from vector in derived class B
virtual void updateList()
{
cPointer->set_sum(getS()); // A is friend of C, so you can access B data from A
}
void callFunc();
};
class B : public A
{
private:
vector<int> list;
void updateList();
int getS() // concrete implementation to access vector data
{
int s = 0;
for (unsigned int i = 0; i < list.size(); i++)
{
s += list[i];
}
return s;
}
public:
void callFromA();
};
A::A()
{
cPointer = C::getCPointer();
}
void A::callFunc()
{
updateList();
}
void B::updateList()
{
list.push_back(2);
list.push_back(4);
A::updateList(); // Call to super implementation
}
void B::callFromA()
{
callFunc();
}
void C::set_sum(int val)
{
sum = val;
cout << "Sum at C is: " << sum << endl;
}
C * C::getCPointer()
{
static C cPointer;
return &cPointer;
}
int main(int argc, char ** argv)
{
B b;
b.callFromA();
return 0;
}
You can not access members of derived classes inside the base class, period. The object at hand might be of the base class, or even of a completely unrelated derived class, with guaranteed "interesting" consecuences. Any design asking for doing so is seriously broken, and needs rethinking.
You can make the member function of the base class which wants to do so virtual, and redefine it in the derived class to do whatever perversion you have in mind. Meanwhile, the chaste member of the base class can just refuse if called, signalling the mistake in a sane way. That way you get a guarantee that nothing too untoward can happen.
I have multiple classes that need to share a single instance of another class. Publicly it should be unknown that this class exists. Is it appropriate to do something like the following? (Was tested as written)
#include <iostream>
class hideme
{
private:
int a;
public:
void set(int b) { a = b; }
void add(int b) { a += b; }
int get() { return a; }
hideme() : a(0) { }
};
class HiddenWrapper
{
protected:
static hideme A;
};
hideme HiddenWrapper::A;
class addOne : public HiddenWrapper
{
public:
void add() { A.add(1); }
int get() { return A.get(); }
};
class addTwo : public HiddenWrapper
{
public:
void add() { A.add(2); }
int get() { return A.get(); }
};
int main()
{
addOne a;
addTwo b;
std::cout << "Initialized: " << a.get() << std::endl;
a.add();
std::cout << "Added one: " << a.get() << std::endl;
b.add();
std::cout << "Added two: " << b.get() << std::endl;
return 0;
}
For what it's worth, hideme is part of a library I'm attempting to design a facade around, and the other classes have members from the library that interact with the static hideme.
Additionally, if the header file written for HiddenWrapper has no corresponding source file, is that the best place to define its static member? With an include guard.
Is there any other method to solve this problem? As far as I could imagine (not terribly far) I could only solve it otherwise with friendship, which I am wary of.
You can prevent access to a class by not making it accessible outside the translation unit that uses it.
// public_header.h
class A {
void bar();
};
class B {
void foo();
}
// private_implementation.cpp
#include "public_header.h"
namespace {
class hidden { void baz() {} };
hidden h;
}
void A::bar() {
h.baz();
}
void B::foo() {
h.baz();
}
This class will be usable only by A::bar and B::foo. The type hidden and the variable h still technically have external linkage, but no other translation unit can say their names.
Sometimes it is a better idea to inject shared ressources (by reference or pointer) through the constructor (also known as composition instead of inheritance). This way gives you the ability to share or not (e.g. to have a thread-safe variant of your code which is not). See http://de.wikipedia.org/wiki/Inversion_of_Control principle for more info.
This implements a singleton around some other class and hides it from
users:
class hideme {};
// fwd declarations
class x;
// library internal
class S
{
S() = delete;
S(S const&) = delete;
void operator=(S const&) = delete;
private:
static hideme& getInstance()
{
static hideme instance;
return instance;
}
friend x;
};
// library classes
class x {
hideme& s;
public:
x() : s(S::getInstance()) {}
};
int main()
{
x x;
return 0;
}
This does not handle cases where you actually want the hideme
instance to be destroyed when no other object is using it anymore. For
that you need to get a little bit more inventive using reference
counting.
I also should say that I think this is a bad idea. Singletons almost
always are.
Generally, the best approach, if you have a variable in the main part, and want to share it with all classes.
For example, if class X makes a change on this var, the change happened to the var in the main as well: you can use EXTEND
************************ The main *********************
#include <iostream>
using namespace std;
#include "Game.hpp"
//0: not specified yet; 1:singlemode; 2:multiplayerMode
int playingMode = 0;
int main()
{
Game game;
game.Run();
std::cout<< playingMode << std::endl;
return 0;
}
*********************** Class X *****************
#include <iostream>
using namespace std;
extern int playingMode;
....
....
if(m_isSinglePressed)
{
playingMode = 1;
...
}
else if(m_isMultiPressed)
{
playingMode = 2;
...
}
Code:
struct Base { ... };
struct A : public Base { ... };
struct B : public Base { ... };
struct C : public Base { ... };
Is it possible to create an array, that holds that types of struct?
sample/expected result:
Type inheritedTypesOfStruct[3] = {A, B, C};
The purpose of this is that I later want to create an object with a random class retrieved from the array.
You could create an array of functions, each of which returns a base pointer(or smart pointer) that each point to objects of your various derived classes. e.g.
typedef std::unique_ptr<Base> base_ptr;
template<typename Derived>
base_ptr CreateObject()
{
return base_ptr(new Derived);
}
int main()
{
std::function<base_ptr(void)> f[3] = {
CreateObject<A>, CreateObject<B>, CreateObject<C>
};
base_ptr arr[10];
for (int i=0; i<10; ++i)
arr[i] = f[rand()%3]();
}
Here it is in action: http://ideone.com/dg4uq
If your compiler supports RTTI, you can do something like:
const type_info *inheritedTypesOfStruct[3] = {
&typeid(A), &typeid(B), &typeid(C)
};
However, you won't be able to instantiate a class using only its type_info. The factory pattern might be a better answer to your root problem.
Update: Since type_info instances cannot be copied (their copy constructor and assignment operator are private), and arrays of references are illegal, constant pointers have to be used in the example above.
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <map>
#include <vector>
#include <memory>
using namespace std;
// interface
class Base
{
public:
virtual ~Base() { }
virtual int getClassId() = 0;
};
// class A relizes interface Base, has ID == 1 (is used in automatic registration to factory)
class A : public Base
{
public:
const static int ID = 1;
static Base* CreateInstance()
{
return new A();
}
virtual int getClassId()
{
return ID;
}
virtual ~A() { }
};
// class B relizes interface Base, has ID == 2 (is used in automatic registration to factory)
class B : public Base
{
public:
const static int ID = 2;
static Base* CreateInstance()
{
return new B();
}
virtual int getClassId()
{
return ID;
}
virtual ~B() { }
};
// this is the objects factory, with registration only (unregister s not allowed)
class ObjectFactory
{
ObjectFactory() { }
ObjectFactory(ObjectFactory&) { }
public:
virtual ~ObjectFactory() { }
static ObjectFactory& instance()
{
static ObjectFactory objectFactory;
return objectFactory;
}
typedef Base* (*Creator) ();
void registerCreator(int id, Creator creator)
{
registry[id] = creator;
}
Base* CreateById(int id)
{
return registry[id]();
}
private:
map<int, Creator> registry;
};
// this template class is used for automatic registration of object's creators
template <class T>
struct RegisterToFactory
{
RegisterToFactory(ObjectFactory& factory)
{
factory.registerCreator(T::ID, &T::CreateInstance);
}
};
namespace
{
// automaticaly register creators for each class
RegisterToFactory<A> autoregisterACreator(ObjectFactory::instance());
RegisterToFactory<B> autoregisterBCreator(ObjectFactory::instance());
}
// lets this this solution
int main(int argc, char *argv[])
{
vector<int> ids;
ids.push_back(static_cast<int>(A::ID));
ids.push_back(static_cast<int>(B::ID));
srand(time(0));
for (int i = 0; i < 20; ++i)
{
int randomClasssId = ids[rand() % ids.size()];
auto_ptr<Base> testObject(ObjectFactory::instance().CreateById(randomClasssId));
cout << "Object of classId = " << testObject->getClassId() << " has been produced by factory." << endl;
}
system("PAUSE");
return EXIT_SUCCESS;
}
I don't get the question. Are you asking for an array that can hold different type of instances at the same time? That is possible using polymorphism, of course. Or are you trying to get an array of types (like reflection)? That would be possible using RTTI or Qt type information (as an example), but I never did that.
You can take a look here: http://www.java2s.com/Code/Cpp/Class/Objectarraypolymorphism.htm
on how to use Polymorphism in C++.