从const字符串进行类实例化的困难 [英] difficulty with class instantiation from const string
问题描述
K,我在这里有一个基类和许多派生类.在基类的下面,在同一个文件中,我有几个对象负责将派生对象注册到具有std :: string索引的map对象中,然后是一个对象,该对象将在给定有效字符串索引的情况下实例化这些对象.要注册一个类对象,我在派生类的私有成员中声明一个DerivedRegister类型的对象,并带有该类的模板参数,然后在类外调用它的构造函数.很简单吧?错误的.由于对象的设置和声明方式不同,因此在对基类进行如此细微的调整时,我总是会收到语法错误.这是我的base.h:
K, what i have here is a base class and numerous derived classes. below the base class, in the same file, i have a couple objects responsible for registering the derived objects in a map object, with std::string indices, and then an object that will instantiate the objects, given a valid string index. To register a class object, i declare an object of type DerivedRegister in the private members of the derived class, with a template parameter of the class, and then call it''s constructor outside the class. Simple enough right? wrong. Because of the way the objects are set up and declared, i keep getting syntax errors when tweaking the base class ever so sligthly. Here is my base.h :
#ifndef BASE_H
#define BASE_H
#include <map>
#include <string>
#include <fstream>
using namespace std;
class base{
#define DECLARE_ENTITY(T) static DerivedRegister<T> reg;
#define LINK_ENTITY(T, name) DerivedRegister<T> T::reg(name);
public:
int getMeh() {return m_meh;}
virtual void GetParams(fstream & stream);
protected:
int m_meh;
string m_EntityName;
};
template<class T> base * createT() {return new T;}
class BaseFactory{
public:
typedef map<string, base *(*)()> map_type;
static base * createInstance(const string & s) {
if ( !getMap()->count(s) )
return NULL;
map_type::iterator it = getMap()->find(s);
return it->second();
}
protected:
static map_type * getMap() {
if(!m_Map) {m_Map = new map_type;}
return m_Map;
}
private:
static map_type * m_Map;
};
template<class T>
class DerivedRegister : BaseFactory {
public:
DerivedRegister(std::string const & s)
{
getMap()-> insert( pair<string, base*(*)()> (s, &createT<T>));
}
};
BaseFactory::map_type * BaseFactory::m_Map = new map_type();
#endif
当我尝试定义base的成员时,这是base.cpp:
here is base.cpp when i''m trying to define a member of base:
#include "base.h"
void base::GetParams(fstream & stream)
{
getline(stream, m_EntityName, ' ');
}
但是,由于某种原因,我收到此错误消息:
base.cpp第5行:BaseFactory :: m_Map
的多个定义
main.cpp第11行:首先在此处定义
这是我正在测试实例化器的main.cpp:
however, for some reason, i get this error message:
base.cpp Line 5 : multiple definition of BaseFactory::m_Map
main.cpp Line 11: first defined here
here is my main.cpp where i was testing out the instantiator:
#include <iostream>
#include <vector>
using namespace std;
#include "base.h"
#include "derived.h"
#include "second.h"
#include "third.h"
#include "fourth.h"
int main()
{
BaseFactory yosh;
vector<base *> meh;
for(int i = 0; i < 20; i++)
{
if(i % 4 == 0)
meh.push_back(yosh.createInstance("derived"));
else if( i % 4 == 1)
meh.push_back(yosh.createInstance("second"));
else if( i % 4 == 2)
meh.push_back(yosh.createInstance("third"));
else
meh.push_back(yosh.createInstance("fourth"));
}
for(int i = 0; i < (int) meh.size(); i++)
{
if(meh[i])
cout << meh[i]->getMeh() << "\n";
else
cout << "invalid\n";
}
for(int i = 0; i < (int) meh.size(); i++)
{
if(meh[i]) delete meh[i];
}
return 0;
}
派生类,第二类,第三类和第四类都是相同的测试类,只是那里的构造函数为m_Meh分配了不同的值.很有启发性.无论如何,这个错误的问题是,我忽略了虚函数,即基类中的GetParams,然后基本上忽略了base.cpp文件中的所有内容,它可以编译并正常工作.那么为什么当我尝试向基类中添加方法时却出现有关重新定义m_Map的错误?
我刚刚意识到,基地工厂的地图可能需要澄清.其中的m_map对象具有类型为std :: string的索引,然后该索引引用指向函数的指针.该函数在该类的上方定义.注册派生类时,它们将template参数传递给自己的类和const字符串.这些用于映射对象的新索引,其中const字符串和模板化函数指针配对在一起.然后,每当我调用成员create实例时,它都会传入const字符串,查看是否存在有效的索引,如果存在,则返回该索引处的函数,该函数将被调用并返回注册到该对象的新实例该const字符串.
derived, second, third, and fourth are all just test classes that are the same except for there constructors which assign different values to m_Meh. It was very enlightening. Anyway, the problem i''m having with this error, is that the moment i omit that virtual function, GetParams from the base class, and then omit basically everything within the base.cpp file, it compiles and works just fine. so why is it that when i try and add a method to the base class, i get errors about the redefinition of m_Map?
i realized just now that the map of the basefactory might need some clarification. the m_map object in there has indices of type std::string, and then the indices refer to pointers to functions. the function is defined just above the class there. when a derived class is registered, they pass in the template parameter to their own class, and a const string. these are used in a new index of the map object where the const string and the templated function pointer are paired together. then anytime i call the member create instance, it passes in the const string, sees if there is a valid index, and if there is, it returns the function at that index, which is called and returns a new instance of the object registered to that const string.
推荐答案
移动
BaseFactory::map_type * BaseFactory::m_Map = new map_type();
添加到您的.cpp文件.
在标头中实例化它意味着每次您包含标头时,它将创建一个新实例.
这就是链接器看到多个定义的原因.
to your .cpp file.
Instantiating it in the header, means that it will create a new instance everytime you include the header.
This is why the linker is seeing multiple definitions.
我认为您不需要base.h中的最后一行.为什么要在那里实例化类成员?
I don''t think you need the final line in base.h. Why are trying to instantiate a class member there?
BaseFactory::map_type * BaseFactory::m_Map = new map_type();
这篇关于从const字符串进行类实例化的困难的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!