Re: Base class static member initialisation
On 12/29/10 10:21 AM, Sanatan wrote:
Hi,
I am trying to create a factory scheme to create objects with a
certain base class.
The pattern I am using is to have a creator class, from which creators
for each
desired type are derived. I then declare a global object of these
creator types.
The base creator class has a static map (keyed by string) that
registers these
objects. This allows people to add new objects and their creators, and
one
can specify the objects to create by passing the string names in a
command line/
config file.
Here is the code:
// BEGIN: base.hpp
#if !defined(BASE_HPP_INCLUDED)
#define BASE_HPP_INCLUDED
#include<string>
#include<map>
using namespace std;
Never do this in a header!
class base
{
private:
protected:
static map<string, base *> c;
base(string name)
{
c[name] = this;
}
public:
static base *getInstance(string name)
{
map<string, base *>::iterator loc = c.find(name);
return ((loc == c.end()) ? 0 : loc->second);
}
virtual string getName() const = 0;
};
map<string, base *> base::c;
This will case base::c to be defined in any compilation unit that
included this header!
#include "base.hpp"
One definition of base::c.
<snip>
#include "base.hpp"
Second definition of base::c.
<snip>
#include "base.hpp"
Third definition of base::c.
<snip>
When I compile, I get the duplicate static initialisation complaint:
$ g++ -o testStatic a.cpp b.cpp testStatic.cpp
/tmp/ccBJjSIu.o:(.bss+0x0): multiple definition of `base::c'
/tmp/ccqWdF5o.o:(.bss+0x0): first defined here
/tmp/cc8bDsEr.o:(.bss+0x0): multiple definition of `base::c'
/tmp/ccqWdF5o.o:(.bss+0x0): first defined here
collect2: ld returned 1 exit status
It would seem that the compiler sees a problem with the static map.
Is there a way of fixing this pattern? I have looked at the discussion
on:
You must have one and only one definition, in a source file, not a header.
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.15
but unfortunately, these solutions won't work for me. I need to be
able
to create these objects by their string names, and want users to not
have
to do much more beyond deriving their class from base, and declare
a global object.
Any suggestions would be appreciated!
If you want to populate a map, create a small class to do it and
instantiate one instance of that class.
--
Ian Collins