ошибка: ожидаемый конструктор, деструктор или преобразование типа перед токеном '('

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

Я ненавижу сообщения об ошибках C++... лол ^^

По сути, я следую тому, что было написано в это сообщение, чтобы попытаться создать фабричный класс для пуль, чтобы их можно было создавать из строки, которая будет анализироваться из файла 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" из верхней части всех подклассов пули.


person jonathanasdf    schedule 11.04.2010    source источник
comment
Мне любопытно, за что был голос против. Это довольно хороший вопрос.   -  person GManNickG    schedule 12.04.2010


Ответы (3)


Вот как вы получаете то, что хотите. (Точно не используя ваш код, пропуская заголовки и т. д. Просто для идеи.):

// 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)

Это работает путем создания глобальной переменной, которая будет инициализирована в какой-то момент во время статической инициализации. Когда это происходит, в своем конструкторе он обращается к глобальному реестру и регистрирует его с именем и функцией, используемой для создания маркеров.

Поскольку статический порядок инициализации не указан, мы помещаем глобальный менеджер в функцию, поэтому при первом вызове этой функции менеджер создается по требованию и используется. Это предотвращает использование неинициализированного менеджера, что могло бы быть, если бы это был простой глобальный объект.

Бесплатно бесплатно попросить разъяснения.

person GManNickG    schedule 11.04.2010

Я не думаю, что вы можете вызывать функции вне функций (пока вы не используете результат для инициализации глобальной).

person UncleBens    schedule 11.04.2010
comment
@jon: ты не хочешь этого делать. Затем вы регистрируетесь каждый раз, когда создаете новый экземпляр пули. - person GManNickG; 12.04.2010
comment
о да. Забыл об этом .. куда тогда лучше всего его положить? - person jonathanasdf; 12.04.2010
comment
@UncleBens: почему глобальные вызовы функций запрещены? - person Lazer; 01.05.2010

reg() — это функция. Вы не можете вызвать функцию без области видимости.

person shoosh    schedule 11.04.2010