从const字符串进行类实例化的困难 [英] difficulty with class instantiation from const string

查看:54
本文介绍了从const字符串进行类实例化的困难的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆