错误:在'('标记之前)的预期构造函数,析构函数或类型转换

时间:2010-04-11 20:39:00

标签: c++ templates factory

include/TestBullet.h:12: error: expected constructor, destructor, or type conver
sion before '(' token

我讨厌C ++错误消息... lol ^^

基本上,我正在按照this post中的内容尝试为子弹创建工厂类,以便可以从字符串中实例化它们,这将从xml文件中解析,因为我没有想要为所有类创建一个带开关的函数,因为这看起来很难看。

这是我的TestBullet.h:

#pragma once

#include "Bullet.h"
#include "BulletFactory.h"

class TestBullet : public Bullet {
public:
    void init(BulletData& bulletData);
    void update();
};

REGISTER_BULLET(TestBullet);  <-- line 12

我的BulletFactory.h:

#pragma once

#include <string>
#include <map>
#include "Bullet.h"

#define REGISTER_BULLET(NAME) BulletFactory::reg<NAME>(#NAME)
#define REGISTER_BULLET_ALT(NAME, CLASS) BulletFactory::reg<CLASS>(NAME)

template<typename T> Bullet * create() { return new T; }

struct BulletFactory {
    typedef std::map<std::string, Bullet*(*)()> bulletMapType;
    static bulletMapType map;

    static Bullet * createInstance(char* s) {
        std::string str(s);
        bulletMapType::iterator it = map.find(str);
        if(it == map.end())
            return 0;
        return it->second();
    }

    template<typename T> 
    static void reg(std::string& s) { 
        map.insert(std::make_pair(s, &create<T>));
    }
};

提前致谢。

与错误无关,但有没有办法让Bullet包含BulletFactory而不会产生大量错误(因为循环包含)?通过这种方式,我可以从所有项目符号子类的顶部删除#include "BulletFactory.h"

3 个答案:

答案 0 :(得分:4)

我认为你不能在函数之外调用函数(只要不使用结果初始化全局函数)。

答案 1 :(得分:2)

reg()是一个功能。你不能在没有范围的情况下调用函数。

答案 2 :(得分:2)

这是你如何得到你想要的。 (完全没有使用你的代码,跳过包括标题等等。仅仅是为了这个想法。):

// bullet_registry.hpp
class bullet;

struct bullet_registry
{
    typedef bullet* (*bullet_factory)(void); 

    std::map<std::string, bullet_factory> mFactories;
};

bullet_registry& get_global_registry(void);

template <typename T>
struct register_bullet
{
    register_bullet(const std::string& pName)
    {
        get_global_registry().mFactories.insert(std::make_pair(pName, create));
    }

    static bullet* create(void)
    {
        return new T();
    }
};

#define REGISTER_BULLET(x) \
        namespace \
        { \
            register_bullet _bullet_register_##x(#x); \
        }

// bullet_registry.cpp
bullet_registry& get_global_registry(void)
{
    // as long as this function is used to get
    // a global instance of the registry, it's
    // safe to use during static initialization
    static bullet_registry result;

    return result; // simple global variable with lazy initialization
}

// bullet.hpp
struct my_bullet : bullet { };

// bullet.cpp
REGISTER_BULLET(my_bullet)

这可以通过创建一个全局变量来实现,该变量将在静态初始化期间的某个时刻初始化。当发生这种情况时,它会在其构造函数中访问全局注册表并使用名称和用于创建项目符号的函数进行注册。

由于未指定静态初始化顺序,我们将全局管理器放在一个函数中,因此在第一次调用该函数时,按需创建管理器并使用它。这使我们无法使用未初始化的管理器,如果它是一个简单的全局对象,则可能就是这种情况。

免费免费要求澄清。