Использование макроса C ++ с аргументами в связанный фрагмент кода - PullRequest
0 голосов
/ 27 февраля 2011

У меня есть макрос, который я использую для ускорения реализации классов Factory. Например, чтобы построить Factory для CameraGenerator, я использую макрос следующим образом: GENERATOR_BUILD_FACTORY_START(CameraGenerator) <br/> ... do some stuff ... <br/> GENERATOR_BUILD_FACTORY_END(CameraGenerator)

Эта сборка, а также создание класса с именем CameraGeneratorFactory. Все это делается в файле .cpp, а не в .h, так что конкретный экземпляр Factory становится глобальной переменной, но конкретное определение фабрики недоступно за пределами этого файла. Все фабрики наследуются от базового класса Factory.

Проблема возникает, когда в другом .cpp мне нужно определить и создать экземпляр другой конкретной фабрики, скажем FileGeneratorFactory, поэтому я делаю

GENERATOR_BUILD_FACTORY_START(FileGenerator) <br/> ... do some other stuff ... <br/> GENERATOR_BUILD_FACTORY_END(FileGenerator)

при компиляции в DEBUG при втором использовании этого макроса снова выполняется конструктор Factory "CameraGenerator", а не правильный фабричный "FileGenerator", как если бы макрос был предварительно обработан, скомпилирован и связан с первым .cpp, он всегда выполняется с одним и тем же аргументом. Повторяю, проблема возникает только при компиляции в режиме отладки .

Кто-нибудь знает что-нибудь об этом поведении?

спасибо в предыдущем

Вот код макроса:

#define GENERATOR_BUILD_FACTORY_START(GEN_NAME) \
    class GEN_NAMEFactory : public AbstractGeneratorFactory{                             \
    public:                                                                              \
       GEN_NAMEFactory() : AbstractGeneratorFactory(){                                   \

#define GENERATOR_BUILD_FACTORY_CONF_SECTION(GEN_NAME) \
           extern GeneratorBuilder generator_builder;                                    \
           generator_builder.add_factory(#GEN_NAME, this);                               

#define GENERATOR_BUILD_FACTORY_END_CONF_SECTION(GEN_NAME) \
       }                                                                                 \
       GEN_NAMEFactory(const GEN_NAMEFactory& f) : AbstractGeneratorFactory(f){}         \
       GEN_NAMEFactory& operator=(const GEN_NAMEFactory& f){                             \
           if (this == &f) return *this;                                                 \
           AbstractGeneratorFactory::operator =(f);                                      \
           return *this;                                                                 \
       }                                                                                 \
       virtual ~GEN_NAMEFactory(){}                                                      \
       virtual Generator* build() const{                                                 \
           return new GEN_NAME();                                                        \
       }                                                                                 \
       Generator* build(const Configuration& cfg) const throw(bad_parameter) {           \
            Generator* g = 0;                                                            \

#define GENERATOR_BUILD_FACTORY_END(GEN_NAME) \
            return g;                                                                    \
        }                                                                                \
    };                                                                                   \
    GEN_NAMEFactory instance_of_GEN_NAMEFactory;

Ответы [ 2 ]

1 голос
/ 27 февраля 2011

Вместо GEN_NAMEFactory вам нужно использовать GEN_NAME##Factory внутри макроса. В противном случае ваш код нарушает правило ODR (вы определяете GEN_NAMEFactory по-разному в двух единицах компиляции). Это вызывает проблемы только при отладке, поскольку только при отладке функции не являются встроенными, и при связывании используется только одна из двух конфликтующих реализаций GEN_NAMEFactory. Вы легко увидите конфликт, если попытаетесь развернуть обе фабрики в одном исходном файле.

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

0 голосов
/ 27 февраля 2011

Не используйте такие макросы, они злые.

Вы могли бы посчитать полезным вместо этого реализовать ваш общий заводской код в виде шаблона C ++.

Но я подозреваю, что все это совершенно неправильно, для этих макросов это все равно, что видеть кого-то, строящего самолет и использующего молоток для ввинчивания винтов.Тогда, как правило, сильно подозревают, что это не поможет предложить отвертку вместо молотка.Скорее всего, когда его спросят, что такое самолет для , человек с некоторой целью ответит, что самолет определенно не является подходящим решением.

Приветствия и hth.,

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...