How to declare a global QWidget? - c++

I want to have a class, which extends QWidget, that I can access in my whole program. I've already tried to declare it in the main.cpp (but this is obsiously not declared in the other files) or to to it after the class declaration (in this case, if I include the file more than once, I get the error multiple declaration).
Is it possible to the Widget as global, and if yes, how ?
Edit :
What I want to do is to write informations on an second window, which is an instance of the class Console (I have written that class).
Then, I have the class MainWindow, with the classes it contains; calculation_widget, and variable_widget, which contain respectively a list of calculations and variables.
I want to be able to write on the Console window from all those classes.

I don't recommend using this, but it would be better than a global pointer. In case you need your window(-s) only once in your application you could use the Singleton (Anti-)pattern.
This is the SingletonTemplate class.
#ifndef __CSingletonTemplate_H__
#define __CSingletonTemplate_H__
template <class T> class CSingletonTemplate
{
public:
static T* GetInstance()
{
if (m_Instance == 0)
{
m_Instance = new T();
}
return m_Instance;
}
static T& GetRefInstance()
{
if (m_Instance == 0)
{
m_Instance = new T();
}
return *m_Instance;
}
static void Release()
{
if (m_Instance != 0)
{
delete m_Instance;
m_Instance = 0;
}
}
protected:
CSingletonTemplate() { ; }; // Hidden constructor
CSingletonTemplate(CSingletonTemplate const&) { ; }; // Hidden copy constructor
CSingletonTemplate& operator=(CSingletonTemplate const&) { ; }; // Hidden assign operation
~CSingletonTemplate() { ; }; // Hidden destructor
private:
static T* m_Instance;
};
template <class T> T* CSingletonTemplate<T>::m_Instance = 0;
#endif // __CSingletonTemplate_H__
You use it by declaring a class like follows:
class MyWindow : public CSingletonTemplate<MyWindow>
{
friend class CSingletonTemplate<MyWindow>;
private:
MyWindow();
virtual ~MyWindow();
Q_DISABLE_COPY(MyWindow);
};
And you can use this class my calling MyWindow::GetInstance()->...
For more information about the Singleton Pattern visit: https://sourcemaking.com/design_patterns/singleton

Related

How to iterate through all typenames in a class template?

I want to design a component-based weapon template for my game. However, it seems no way to add/remove a class member or create a code?
Sorry for my expression and lack of terminology, for I am not graduated from dept. of computer science or software engineer, I know little of what those stuff called by professionals.
Here is the component code looks like:
class CBaseWpnCmpt : public std::enable_shared_from_this<CBaseWpnCmpt>
{
public:
typedef std::shared_ptr<CBaseWpnCmpt> PTR;
private:
CBaseWpnCmpt() = default;
public:
CBaseWpnCmpt(const CBaseWpnCmpt& s) = default;
CBaseWpnCmpt(CBaseWpnCmpt&& s) = default;
CBaseWpnCmpt& operator=(const CBaseWpnCmpt& s) = default;
CBaseWpnCmpt& operator=(CBaseWpnCmpt&& s) = default;
virtual ~CBaseWpnCmpt() {}
protected:
CBaseWeaponInterface::PTR m_pWeapon { nullptr };
public:
template <class CComponent>
static std::shared_ptr<CComponent> Create(CBaseWeaponInterface::PTR pWeapon)
{
std::shared_ptr<CComponent> pComponent = std::make_shared<CComponent>();
pComponent->m_pWeapon = pWeapon;
return pComponent;
}
};
And this is what a weapon body code looks like: (And the problem occurs)
template < class CWeapon,
class ...CComponents
>
class CBaseWeaponTemplate : public CBaseWeaponInterface
{
public:
std::list<CBaseWpnCmpt::PTR> m_lstComponents;
public:
virtual void SecondaryAttack(void) // Example method.
{
for (auto& pComponent : m_rgpComponents)
{
pComponent->SecondaryAttack();
}
}
};
How am I suppose to create all these argument packs as member of the template? Currently I tried to enlist them into a pointer std::list container, but I just can't figure out how to achieve it at all.
In other words, how can I make a template when I fill in blank likt this:
class CAK47 : public CBaseWeaponTemplate<CAK47, CLongMagazine, CWoodenStock>
will generate this:
class CAK47
{
CLongMagazine m_comp1;
CWoodenStock m_comp2;
//... other stuff
};
Or alternatively, generate this:
class CAK47
{
CAK47() // constructor
{
for (/* somehow iterate through all typenames */)
{
CBaseWpnCmpt::PTR p = std::make_shared<typename>();
m_lstComponents.emplace_back(p);
}
}
};
One way of doing so from C++11 on-wards would be to store the template types used for this particular weapon inside an std::tuple
template <typename Weapon, typename... Attachments>
class WeaponWithAttachments {
protected:
WeaponWithAttachments() {
return;
}
std::tuple<Attachments...> attachment_types;
};
and then using that tuple to initialise a vector of shared pointers with a protected constructor taking a tuple to access the template types again.
class SomeWeaponWithAttachments: public WeaponWithAttachments<SomeWeapon,SomeAttachment,AnotherAttachment> {
public:
SomeWeaponWithAttachments()
: SomeWeaponWithAttachments{attachment_types} {
return;
}
protected:
template <typename... Attachments>
SomeWeaponWithAttachments(std::tuple<Attachments...> const&)
: attachments{std::make_shared<Attachments>()...} {
return;
}
std::vector<std::shared_ptr<BaseAttachment>> attachments;
};
Try it here!
If the attachments vector is already declared inside the parent class like it seems to be the case for you might also avoid the tuple and the protected constructor with initialising the attachments already inside the parent class
template <typename Weapon, typename... Attachments>
class WeaponWithAttachments {
protected:
WeaponWithAttachments()
: attachments{std::make_shared<Attachments>()...} {
return;
}
std::vector<std::shared_ptr<BaseAttachment>> attachments;
};
and then only calling the constructor of the base class in the derived class
class SomeWeaponWithAttachments: public WeaponWithAttachments<SomeWeapon,SomeAttachment,AnotherAttachment> {
public:
SomeWeaponWithAttachments()
: WeaponWithAttachments<SomeWeapon,SomeAttachment,AnotherAttachment>() {
return;
}
};
Try it here!
If that is no option for you, then you can use the tuple to iterate over all the template arguments using C++17 fold expressions:
class SomeWeaponWithAttachments: public WeaponWithAttachments<SomeWeapon,SomeAttachment,AnotherAttachment> {
public:
SomeWeaponWithAttachments()
: SomeWeaponWithAttachments{attachment_types} {
return;
}
protected:
template <typename... Attachments>
SomeWeaponWithAttachments(std::tuple<Attachments...> const&) {
(attachments.push_back(std::make_shared<Attachments>()), ...);
return;
}
};
Try it here!
In C++17 you might also add a static assertion with fold expressions into the constructor to make sure that the types actually inherit from BaseAttachment:
static_assert((std::is_base_of_v<BaseAttachment, Attachments> && ...), "Template arguments must inherit from 'BaseAttachment'.");

C++ singleton template class crashes my program

I created a singleton pattern as a template class.
template <typename T>
class TemplateSingleton
{
protected:
TemplateSingleton() { }
virtual ~TemplateSingleton() { }
public:
static T * GetInstance()
{
if (m_pInstance == NULL)
m_pInstance = new T;
return m_pInstance;
};
static void FreeInstance()
{
if (m_pInstance != NULL)
{
delete m_pInstance;
m_pInstance = NULL;
}
};
private:
static T * m_pInstance;
};
template <typename T> T * TemplateSingleton<T>::m_pInstance = NULL;
And use inherited from child class.
This class can be used as a singleton by inheriting a template, or as a generic class if not inherited.
#define MAX_COUNT 8
class CDataHandler : public TemplateSingleton<CDataHandler>
{
public:
CDataHandler();
~CDataHandler();
...
private:
CDataObj m_clDataObj[MAX_COUNT]; // CDataObj *m_clDataObj ?
DWORD m_dwDataObjCount;
...
};
class CDataObj
{
public:
CDataObj();
~CDataObj();
...
private:
...
};
The code above is in a DLL, and the program is implemented to call only the instance constructor of CDataHandler.
And my program crashes and quits.
By the way, if I change CDataObj member variable from array to pointer, it works fine.
(In this case, new in the constructor of the CDataHandler, and delete in the destructor.)
Is there something wrong with this code?
Addition)
constructor and destructor code for CDataHandler :)
CDataHandler::CDataHandler()
: m_dwDataObjCount(0)
//, m_clDataObj(NULL)
{
// Do nothing
// m_clDataObj = new CDataObj[MAX_COUNT];
}
CDataHandler::~CDataHandler()
{
//if (m_clDataObj != NULL)
{
for (int i = 0; i < MAX_COUNT; i++)
{
m_clDataObj[i].Close();
}
// delete[] m_clDataObj;
// m_clDataObj = NULL;
}
}
Not sure what is causing your program to crash, but there are two potential problems in the code you posted.
First, you don't know when m_pInstance will be initialised to NULL. If you call GetInstance() during static data initialisation, m_pInstance might not yet be initialised to NULL and thus GetInstance() will return some invalid pointer. Look up "static data initialisation order fiasko" or something like this, there is a lot of information on this.
To avoid this, you can use local static variables, along the lines of:
T* GetInstance()
{
static T* t = new T{};
return t;
}
Second, you use a template for your singleton. That's okay, but you have to take care: If the definition of the class is available to more than one compilation unit, each of these compilation units will instantiate their own singleton, leaving you with multiple different instances depending on from which compilation unit you are accessing them.
To solve this, you can use extern template for a certain T in the DLL to tell others they should not instantiate this template specialisation and then compile an explicit template instantiation into the DLL to provide the implementation for everyone.

Singleton file static vs class private static

Is there any difference or specific advice when it comes to the following approaches for defining singletons?
In 1, the singleton object is a class private static, but in 2, it's a file static.
Note: m_initedObj1 is just there to show that class has state, and use case is to call this singleton->DoSomething() many times, without needing to init this object again.
1)
// header file
class Foo {
private:
static Foo* s_fooSingleton;
Foo();
Obj1 m_initedObj1;
public:
static Foo* Singleton();
static void ClearSingleton();
Bar DoSomething(...);
};
// cpp file
Foo* Foo::s_fooSingleton = nullptr;
Foo::Foo() { m_initedObj1 = InitObj1Somewhere(); }
/*static*/ Foo* Foo::Singleton()
{
if(!Foo::s_fooSingleton)
Foo::s_fooSingleton = new Foo();
return Foo::s_fooSingleton;
}
/*static*/ void Foo::ClearSingleton()
{
if(Foo::s_fooSingleton)
delete Foo::s_fooSingleton;
Foo::s_fooSingleton = nullptr;
}
Bar Foo::DoSomething(...) { // do something }
2)
// header file
class Foo {
private:
Foo();
Obj1 m_initedObj1;
public:
static Foo* Singleton();
static void ClearSingleton();
Bar DoSomething(...);
};
// cpp file
static Foo* s_fooSingleton = nullptr;
Foo::Foo() { m_initedObj1 = InitObj1Somewhere(); }
/*static*/ Foo* Foo::Singleton()
{
if(!s_fooSingleton)
s_fooSingleton = new Foo();
return s_fooSingleton;
}
/*static*/ void Foo::ClearSingleton()
{
if(s_fooSingleton)
delete s_fooSingleton;
s_fooSingleton = nullptr;
}
Bar Foo::DoSomething(...) { // do something }
As JerryGoyal states in the comments, in 2) other methods in the same .cpp file can modify s_fooSingleton.
On the other hand, they are not both thread-safe. If you don't really mind the clearing (calling ClearSingleton() explicitly), just go with the Scott Meyers' version. Otherwise, go with the double checked locking version.
It's really hard to ensure the safety in case of explicitly deleting. You always have to check whether it's deleted before you access it. If it's a multi-threaded executable, checking and using it must be atomic, because it can be deleted just after checking.
Double checked locking could be used to create and delete the singleton, which ensures you that there is only one instance at a time. Yet, it does not ensure the object really exist, since you may accidentally delete it.
You may use smart pointers to count references and delete it if no references exist.
Or even better, see this answer https://stackoverflow.com/a/15733545/1632887.
I just wouldn't delete it explicitly if I were you!
Maybe this will satisfy you more:
class MyClass1 {
private:
MyClass1(){}
public:
MyClass1& Instance() {
static MyClass1 theSingleInstance;
return theSingleInstance;
}
};
class MyClass2 {
private:
MyClass2() {}
public:
MyClass2* Instance() {
static MyClass2* theSingleInstance = new MyClass2;
return theSingleInstance;
}
};
class MyClass3 {
private:
MyClass3() {}
public:
MyClass3* Instance() {
static MyClass3 theSingleInstance;
return &theSingleInstance;
}
};

C++ finding the instantiated templates

I have just discovered the following jewel in the code (the example is very simplified, but the logic is the same):
template <class T>
class garbage_bin
{
private:
garbage_bin<T>(void)
{
}
static garbage_bin<T>* pinstance;
public:
static garbage_bin<T>& instance()
{
if(pinstance == NULL)
{
pinstance = new garbage_bin<T>();
}
return *pinstance;
}
void empty()
{
for(size_t i=0; i<items.size(); i++)
{
free (items[i]);
}
}
void throwIn(T item)
{
items.push_back(item);
}
vector<T> items;
};
and then somewhere in the code (this is just ONE example ... there are thousands like this):
char* r = strdup(src);
garbage_bin<char*>::instance().throwIn(r);
and later somewhere in the code, right before the exit ...
garbage_bin<char*>::instance().empty();
garbage_bin<molecules*>::instance().empty();
garbage_bin<CDatabaseUsers*>::instance().empty();
and so on ...
so as we can see, this implements a garbage bin class, in which you can "throw in" all kind of objects, and at a later stage to avoid the memory leaks you "empty" the garbage bin. But here comes the big bottleneck: In order for this to work properly, you need to know all the classes for which this garbage bin was instantiated in order to empty them...
The most direct solution I was thinking of is to create a map of typeid calls for the instantiations, and assign the garbage_bin<T>::instance() to the name however an ancient compiler decided that he does not like this approach.
Obviously, I can make a search through the code to find all the templatizations, but I'm wondering ... is there a simpler way to do this?
Garbage bin bin!
class garbage_bin_base;
class garbage_bin_bin {
public:
void throwIn(garbage_bin_base* rubbish) { items.push_back(rubbish); }
void empty() { for (auto item: items) item->empty(); }
private:
vector<garbage_bin_base*> items;
};
class garbage_bin_base {
public:
virtual empty() = 0;
garbage_bin_base() { garbage_bin_bin::instance().throwIn(this); }
};
template <typename T>
class garbage_bin : public garbage_bin_base {
};
You could add a registry for things to be deleted:
Registry registry;
// ...
if (pinstance == NULL)
{
pinstance = new garbage_bin<T>();
registry.add<T>();
}
// ...
registry.clear_all();
For example:
class Registry
{
struct Base
{
virtual ~Base() {}
virtual void clear() = 0;
};
template <typename T> struct Derived : Base
{
virtual void clear() { garbage_bin<T*>::instance().empty(); }
};
std::vector<std::unique_ptr<Base>> targets;
public:
void clear_all() { for (auto & p : targets) { p->clear(); } }
template <typename T> void add()
{
targets.emplace_back(new Derived<T>);
}
};
I would rather replace garbage_bin<T> with std::vector<std::unique_ptr<T>> (or, maybe, std::vector<std::shared_ptr<T>>).
If you want to restrict the interface, then reimplement garbage_bin<T> as a wrapper around std::vector<std::unique_ptr<T>>. In this way, you probably don't need the empty method since the destructors of std::vector and std::unique_ptr will clean-up after themselves. However, if you want to empty the bin before destruction, then implement empty just calling std::vector::clear.
I understand that this is not exactly the simplest thing to do (because the OP says there are "thousands" of places to be changed) but a refactoring of this bad design is clearly needed.

Looking for a better C++ class factory

I have an application that has several objects (about 50 so far, but growing). There is only one instance of each of these objects in the app and these instances get shared among components.
What I've done is derive all of the objects from a base BrokeredObject class:
class BrokeredObject
{
virtual int GetInterfaceId() = 0;
};
And each object type returns a unique ID. These IDs are maintained in a header file.
I then have an ObjectBroker "factory". When someone needs an object, then call GetObjectByID(). The boker looks in an STL list to see if the object already exists, if it does, it returns it. If not, it creates it, puts it in the list and returns it. All well and good.
BrokeredObject *GetObjectByID(int id)
{
BrokeredObject *pObject;
ObjectMap::iterator = m_objectList.find(id);
// etc.
if(found) return pObject;
// not found, so create
switch(id)
{
case 0: pObject = new TypeA; break;
case 1: pObject = new TypeB; break;
// etc.
// I loathe this list
}
// add it to the list
return pObject;
}
What I find painful is maintaining this list of IDs and having to have each class implement it. I have at least made my consumer's lives slightly easier by having each type hold info about it's own ID like this:
class TypeA : public BrokeredObject
{
static int get_InterfaceID() { return IID_TYPEA; }
int GetInterfaceID() { return get_InterfaceID(); }
};
So I can get an object like this:
GetObjectByID(TypeA::get_InterfaceID());
Intead of having to actually know what the ID mapping is but I still am not thrilled with the maintenance and the potential for errors. It seems that if I know the type, why should I also have to know the ID?
What I long for is something like this in C#:
BrokeredObject GetOrCreateObject<T>() where T : BrokeredObject
{
return new T();
}
Where the ObjectBroker would create the object based on the type passed in.
Has C# spoiled me and it's just a fact of life that C++ can't do this or is there a way to achieve this that I'm not seeing?
Yes, there is a way. A pretty simple even in C++ to what that C# code does (without checking for inheritance though):
template<typename T>
BrokeredObject * GetOrCreateObject() {
return new T();
}
This will work and do the same as the C# code. It is also type-safe: If the type you pass is not inherited from BrokeredObject (or isn't that type itself), then the compiler moans at the return statement. It will however always return a new object.
Singleton
As another guy suggested (credits to him), this all looks very much like a fine case for the singleton pattern. Just do TypeA::getInstance() to get the one and single instance stored in a static variable of that class. I suppose that would be far easier than the above way, without the need for IDs to solve it (i previously showed a way using templates to store IDs in this answer, but i found it effectively is just what a singleton is).
I've read that you will leave the chance open to have multiple instances of the classes. One way to do that is to have a Mingleton (i made up that word :))
enum MingletonKind {
SINGLETON,
MULTITON
};
// Singleton
template<typename D, MingletonKind>
struct Mingleton {
static boost::shared_ptr<D> getOrCreate() {
static D d;
return boost::shared_ptr<D>(&d, NoopDel());
}
struct NoopDel {
void operator()(D const*) const { /* do nothing */ }
};
};
// Multiton
template<typename D>
struct Mingleton<D, MULTITON> {
static boost::shared_ptr<D> getOrCreate() {
return boost::shared_ptr<D>(new D);
}
};
class ImASingle : public Mingleton<ImASingle, SINGLETON> {
public:
void testCall() { }
// Indeed, we have to have a private constructor to prevent
// others to create instances of us.
private:
ImASingle() { /* ... */ }
friend class Mingleton<ImASingle, SINGLETON>;
};
class ImAMulti : public Mingleton<ImAMulti, MULTITON> {
public:
void testCall() { }
// ...
};
int main() {
// both do what we expect.
ImAMulti::getOrCreate()->testCall();
ImASingle::getOrCreate()->testCall();
}
Now, you just use SomeClass::getOrCreate() and it cares about the details. The custom deleter in the singleton case for shared_ptr makes deletion a no-op, because the object owned by the shared_ptr is allocated statically. However, be aware of problems of destruction order of static variables: Static initialization order fiasco
The way I would solve this problem is using what I would call the Static Registry Pattern, which in my mine mind is the C++ version of dependency injection.
Basically you have a static list of builder objects of a type that you use to build objects of another type.
A basic static registry implementation would look like:
template <class T>
class StaticRegistry
{
public:
typedef std::list<T*> Container;
static StaticRegistry<T>& GetInstance()
{
if (Instance == 0)
{
Instance = new StaticRegistry<T>;
}
return *Instance;
}
void Register(T* item)
{
Items.push_back(item);
}
void Deregister(T* item)
{
Items.remove(item);
if (Items.empty())
{
delete this;
Instance = 0;
}
}
typedef typename Container::const_iterator const_iterator;
const_iterator begin() const
{
return Items.begin();
}
const_iterator end() const
{
return Items.end();
}
protected:
StaticRegistry() {}
~StaticRegistry() {}
private:
Container Items;
static StaticRegistry<T>* Instance;
};
template <class T>
StaticRegistry<T>* StaticRegistry<T>::Instance = 0;
An implementation of BrokeredObjectBuilder could look like this:
class BrokeredObjectBuilderBase {
public:
BrokeredObjectBuilderBase() { StaticRegistry<BrokeredObjectBuilderBase>::GetInstance().Register(this); }
virtual ~BrokeredObjectBuilderBase() { StaticRegistry<BrokeredObjectBuilderBase>::GetInstance().Deregister(this); }
virtual int GetInterfaceId() = 0;
virtual BrokeredObject* MakeBrokeredObject() = 0;
};
template<class T>
class BrokeredObjectBuilder : public BrokeredObjectBuilderBase {
public:
BrokeredObjectBuilder(unsigned long interface_id) : m_InterfaceId(interface_id) { }
virtual int GetInterfaceId() { return m_InterfaceId; }
virtual T* MakeBrokeredObject() { return new T; }
private:
unsigned long m_InterfaceId;
};
class TypeA : public BrokeredObject
{
...
};
// Create a global variable for the builder of TypeA so that it's
// included in the BrokeredObjectBuilderRegistry
BrokeredObjectBuilder<TypeA> TypeABuilder(TypeAUserInterfaceId);
typedef StaticRegistry<BrokeredObjectBuilderBase> BrokeredObjectBuilderRegistry;
BrokeredObject *GetObjectByID(int id)
{
BrokeredObject *pObject(0);
ObjectMap::iterator = m_objectList.find(id);
// etc.
if(found) return pObject;
// not found, so create
BrokeredObjectBuilderRegistry& registry(BrokeredObjectBuilderRegistry::GetInstance());
for(BrokeredObjectBuilderRegistry::const_iterator it = registry.begin(), e = registry.end(); it != e; ++it)
{
if(it->GetInterfaceId() == id)
{
pObject = it->MakeBrokeredObject();
break;
}
}
if(0 == pObject)
{
// userinterface id not found, handle this here
...
}
// add it to the list
return pObject;
}
Pros:
All the code that knows about creating the types is seperated out into the builders and the BrokeredObject classes don't need to know about it.
This implementation can be used in libraries and you can control on a per project level what builders are pulled into a project using a number of different techniques.
The builders can be as complex or as simple (like above) as you want them to be.
Cons:
There is a wee bit of infrastructure involved (but not too much).
The flexability of defining the global variables to include what builders to include in your project does make it a little messy to work with.
I find that people find it hard to understand this pattern, I'm not sure why.
It's sometimes not easy to know what is in the static registry at any one time.
The above implementation leaks one bit of memory. (I can live with that...)
The above implementation is very simple, you can extend it in lots of different ways depending on the requirements you have.
Use a template class as the broker.
Make the instance a static member of the function. It will be created on first use and automagically-destroyed when the program exits.
template <class Type>
class BrokeredObject
{
public:
static Type& getInstance()
{
static Type theInstance;
return theInstance;
}
};
class TestObject
{
public:
TestObject()
{}
};
int main()
{
TestObject& obj =BrokeredObject<TestObject>::getInstance();
}
Instead of GetInterfaceId() in the BrokeredObject base class, you could define that pure virtual method:
virtual BrokeredObject& GetInstance()=0;
And in the derived classes you'll return from that method the instance of the particular derived class, if it's already created, if not, you'll first create it and then return it.
It doesn't look like you need the global object to do the management, so why not move everything into the classes themselves?
template <class Type>
class BrokeredObject
{
protected:
static Type *theInstance;
public:
static Type *getOrCreate()
{
if (!theInstance) {
theInstance = new Type();
}
return theInstance;
}
static void free()
{
delete theInstance;
}
};
class TestObject : public BrokeredObject<TestObject>
{
public:
TestObject()
{}
};
int
main()
{
TestObject *obj = TestObject::getOrCreate();
}
If you have RTTI enabled, you can get the class name using typeid.
One question, why are you using a factory rather than using a singleton pattern for each class?
Edit: OK, so you don't want to be locked into a singleton; no problem. The wonderful thing about C++ is it gives you so much flexibility. You could have a GetSharedInstance() member function that returns a static instance of the class, but leave the constructor public so that you can still create other instances.
If you always know the type at compile time there is little point in calling BrokeredObject* p = GetObjectByID(TypeA::get_InterfaceID()) instead of TypeA* p = new TypeA or TypeA o directly.
If you on the other hand don't know the exact type at compile time, you could use some kind of type registry.
template <class T>
BrokeredObject* CreateObject()
{
return new T();
}
typedef int type_identity;
typedef std::map<type_identity, BrokeredObject* (*)()> registry;
registry r;
class TypeA : public BrokeredObject
{
public:
static const type_identity identity;
};
class TypeB : public BrokeredObject
{
public:
static const type_identity identity;
};
r[TypeA::identity] = &CreateObject<TypeA>;
r[TypeB::identity] = &CreateObject<TypeB>;
or if you have RTTI enabled you could use type_info as type_identity:
typedef const type_info* type_identity;
typedef std::map<type_identity, BrokeredObject* (*)()> registry;
registry r;
r[&typeid(TypeA)] = &CreateObject<TypeA>;
r[&typeid(TypeB)] = &CreateObject<TypeB>;
Each new class could of course, in any case, be self-registering in the registry, making the registration decentralized instead of centralized.
You should almost certainly be using dependency injection.
Why not this?
template
BrokeredObject* GetOrCreateObject()
{
return new T();
}
My use-case tended to get a little more complex - I needed the ability to do a little bit of object initialization and I needed to be able to load objects from different DLLs based on configuration (e.g. simulated versus actual for hardware). It started looking like COM and ATL was where I was headed, but I didn't want to add the weight of COM to the OS (this is being done in CE).
What I ended up going with was template-based (thanks litb for putting me on track) and looks like this:
class INewTransModule
{
public:
virtual bool Init() { return true; }
virtual bool Shutdown() { return true; }
};
template <typename T>
struct BrokeredObject
{
public:
inline static T* GetInstance()
{
static T t;
return &t;
}
};
template <>
struct BrokeredObject<INewTransModule>
{
public:
inline static INewTransModule* GetInstance()
{
static INewTransModule t;
// do stuff after creation
ASSERT(t.Init());
return &t;
}
};
class OBJECTBROKER_API ObjectBroker
{
public:
// these calls do configuration-based creations
static ITraceTool *GetTraceTool();
static IEeprom *GetEeprom();
// etc
};
Then to ensure that the objects (since they're templated) actually get compiled I added definitions like these:
class EepromImpl: public BrokeredObject<EepromImpl>, public CEeprom
{
};
class SimEepromImpl: public BrokeredObject<SimEepromImpl>, public CSimEeprom
{
};