Здравствуйте, Mechanicus, Вы писали:
M> module.cpp
M> M> . . .
M> Module::worldFactory_t Module::worldFactory_;
M> . . .
M>
M> module.h
M> M> . . .
M> class Module
M> {
M> public:
M> static bool registerWorld(World *(*createFn)())
M> {
M> std::cout << "World is registered." << std::endl;
M> worldFactory_ = createFn;
M> return true;
M> }
M> . . .
M>
M> world.cpp
M> M> . . .
M> static bool world_registered = Module::registerWorld(create);
M> . . .
M>
M> При компиляции с помощю mingw(gcc-3.3.1) и выполнении
M> этой программы стабильно на cout выдаётся World is registered.
M> call to empty boost::function
M> done.
Подозреваю, что сначала вызывается registerWorld, а
затем — конструктор
boost::function для объекта Module::worldFactory_, что приводит к обнулению
указателя, в нем содержащегося.
M> VC7.0 всё компилит и выполняет нормально. Я даже не знаю кто тут прав, вроде
M> код верный, и VC прав, хотя кто его знает.
Оба правы: стандарт не гарантирует порядок инициализации глобальных объектов в
разных единицах трансляции.
Для решения можно, например, заменить статическую переменную-член worldFactory_
на статическую функцию вида:
/* static */
Module::worldFactory_t& Module::worldFactory_()
{
static Module::worldFactory_t theFactory;
return theFactory;
}
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Вот натолкнулся на такую проблему с использованием субжа. Есть два модуля
module.cpp
#include "module.h"
#include <exception>
#include <iostream>
#include <boost/bind.hpp>
Module::worldFactory_t Module::worldFactory_;
bool Module::init()
{
getWorld();
return true;
}
int main()
{
try {
Module::create()->init();
}
catch (std::exception &ex) {
std::cout << ex.what() << std::endl;
}
std::cout << "done." << std::endl;
return 0;
}
module.h
#ifndef MODULE_H
#define MODULE_H
#include <boost/function.hpp>
#include <boost/utility.hpp>
#include <iostream>
class World;
class Module
{
public:
static bool registerWorld(World *(*createFn)())
{
std::cout << "World is registered." << std::endl;
worldFactory_ = createFn;
return true;
}
World *getWorld()
{
return worldFactory_();
}
static Module *create()
{
static Module obj_;
return &obj_;
}
bool init();
private:
typedef boost::function0<World *> worldFactory_t;
static worldFactory_t worldFactory_;
};
#endif
и
world.cpp
#include "module.h"
#include "world.h"
namespace
{
World *create()
{
static World obj;
return &obj;
}
static bool world_registered =
Module::registerWorld(create);
}
world.h
#ifndef AAA
#define AAA
#include <boost/utility.hpp>
class World : boost::noncopyable
{
};
#endif //AAA
При компиляции с помощю mingw(gcc-3.3.1) и выполнении этой программы стабильно на cout выдаётся
World is registered.
call to empty boost::function
done.
VC7.0 всё компилит и выполняет нормально. Я даже не знаю кто тут прав, вроде код верный, и VC прав, хотя кто его знает.
... << RSDN@Home 1.1.3 beta 1 >>
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Подозреваю, что сначала вызывается registerWorld, а затем — конструктор
ПК>boost::function для объекта Module::worldFactory_, что приводит к обнулению
ПК>указателя, в нем содержащегося.
Блин. Точно. Я знал что function где-то обнуляется, но никак не мог понять где.
M>> VC7.0 всё компилит и выполняет нормально. Я даже не знаю кто тут прав, вроде
M>> код верный, и VC прав, хотя кто его знает.
ПК>Оба правы: стандарт не гарантирует порядок инициализации глобальных объектов в
ПК>разных единицах трансляции.
Кстати есть ещё такое момент. Можно ли писать так?
1.cpp
namespace {
bool reg = ....;
}
2.cpp
namespace {
bool reg = ....;
}
VC7.0 при линковке ругается на то, что reg уже определён в другом модуле. Разве он прав
... << RSDN@Home 1.1.3 beta 1 >>
Здравствуйте, Mechanicus, Вы писали:
M> Можно ли писать так?
M> M> 1.cpp
M> namespace {
M> bool reg = ....;
M> }
M> 2.cpp
M> namespace {
M> bool reg = ....;
M> }
M>
Можно.
M> VC7.0 при линковке ругается на то, что reg уже определён в другом модуле.
M> Разве он прав
Неправ. Ты уверен, что код привел точно?
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
M>> Можно ли писать так?
M>> M>> 1.cpp
M>> namespace {
M>> bool reg = ....;
M>> }
M>> 2.cpp
M>> namespace {
M>> bool reg = ....;
M>> }
M>>
ПК>Можно.
M>> VC7.0 при линковке ругается на то, что reg уже определён в другом модуле.
M>> Разве он прав
ПК>Неправ. Ты уверен, что код привел точно?
Дело в том, что прям так выделить его в два файла у меня не получилось. У меня в файлах примерно такой код регистрации.
namespace {
bool registered =
startup::ModuleLibrary::instance()->registerModule(
cfg::Module::create()
);
};
В различных файлах меняется либо пространстов имён cfg на другое, либо совсем другие функции регистрации вызываются, но линкер железно выдаёт.
error LNK2005: "bool `anonymous namespace'::registered" (?registered@?A0xbb0ee478@@3_NA) already defined in module3.obj
gcc всё компилирует и линкует нормально.
... << RSDN@Home 1.1.3 beta 1 >>