c – 为什么静态数据成员不能初始化?
我正在尝试在加载时注册一堆类的工厂.我的策略是利用静态初始化来确保在main()开始之前,工厂已准备就绪.当我动态链接我的库时,这个策略似乎有效,但是当我静态链接时,这种策略似乎没有用.当我静态链接时,只有一些静态数据成员被初始化.
让我们说我的工厂建造汽车.我有CarCreator类可以实例化一些汽车,但不是全部.我希望工厂收集所有这些CarCreator类,以便寻找新车的代码可以去工厂而不必知道谁将进行实际构造. 所以我有 CarTypes.hpp enum CarTypes { prius = 0,miata,hooptie,n_car_types }; MyFactory.hpp class CarCreator { public: virtual Car * create_a_car( CarType ) = 0; virtual std::list< CarTypes > list_cars_I_create() = 0; }; class MyFactory // makes cars { public: Car * create_car( CarType type ); void factory_register( CarCreator * ) static MyFactory * get_instance(); // singleton private: MyFactory(); std::vector< CarCreator * > car_creator_map; }; MyFactory.cpp MyFactory:: MyFactory() : car_creator_map( n_car_types ); MyFactory * MyFactory::get_instance() { static MyFactory * instance( 0 ); /// Safe singleton if ( instance == 0 ) { instance = new MyFactory; } return instance; } void MyFactory::factory_register( CarCreator * creator ) { std::list< CarTypes > types = creator->list_cars_I_create(); for ( std::list< CarTypes >::const_iteator iter = types.begin(); iter != types.end(); ++iter ) { car_creator_map[ *iter ] = creator; } } Car * MyFactory::create_car( CarType type ) { if ( car_creator_map[ type ] == 0 ) { // SERIOUS ERROR! exit(); } return car_creator_map[ type ]->create_a_car( type ); } … 然后我会有特定的汽车和特定的汽车创造者: Miata.cpp class Miata : public Car {...}; class MiataCreator : public CarCreator { public: virtual Car * create_a_car( CarType ); virtual std::list< CarTypes > list_cars_I_create(); private: static bool register_with_factory(); static bool registered; }; bool MiataCreator::register_with_factory() { MyFactory::get_instance()->factory_register( new MiataCreator ); return true; } bool MiataCreator::registered( MiataCreator::register_with_factory() ); … 重申:动态链接我的库,MiataCreator :: registered将被初始化,静态链接我的库,它不会被初始化. 使用静态构建,当有人去工厂请求Miata时,car_creator_map的miata元素将指向NULL并且程序将退出. 私有静态整数数据成员有什么特别之处,它们的初始化将以某种方式被跳过?是否仅在使用类时初始化静态数据成员?我的CarCreator类未在任何头文件中声明;它们完全位于.cpp文件中.是否有可能编译器内联初始化函数并以某种方式避免调用MyFactory :: factory_register? 这个注册问题有更好的解决方案吗? 不能在单个函数中列出所有CarCreators,使用工厂明确注册每个CarCreators,然后保证调用该函数.特别是,我想将几??个库链接在一起并在这些单独的库中定义CarCreators,但仍然使用单个工厂来构造它们. … 以下是我期待的一些回复,但没有解决我的问题: 1)您的单件工厂不是线程安全的. 2)当你的CarCreator被初始化时你的单件工厂可能未被初始化(即你有一个静态初始化惨败) 解决方法
我认为你有一个静态初始化命令fiasco,但不是与Factory.
这并不是说注册标志没有被初始化,它只是没有尽快初始化. 您不能依赖静态初始化顺序,除非: >将在列出的顺序中初始化在同一翻译单元(.cpp文件)中定义的静态变量 你不能依赖的是静态变量将在第一次调用某个其他翻译单元中的函数或方法之前被初始化. 特别是,在第一次调用MyFactory :: create_car(在MyFactory.cpp中定义)之前,不能依赖MiataCreator :: registered(在Miata.cpp中定义)进行初始化. 像所有未定义的行为一样,有时候你会得到你想要的东西,有时你也不会,而最奇怪的看似无关的东西(如静态与动态链接)可以改变它是否以你想要的方式工作. 您需要做的是为Miata.cpp中定义的已注册标志创建静态访问器方法,并让MyFactory工厂通过此访问器获取值.由于访问器与变量定义位于相同的转换单元中,因此变量将在访问器运行时初始化.然后,您需要从某个地方调用此访问器. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |