Bagaimana untuk Mengkonfigurasi Objek daripada Rentetan yang Mengandungi Nama Kelasnya?
Dalam kod yang diberikan, kelas BaseFactory mencipta objek daripada kelas Terbitan yang berbeza berdasarkan rentetan yang mewakili nama kelas mereka. Walau bagaimanapun, kilang memerlukan penambahan manual pernyataan if untuk setiap kelas Terbitan yang mungkin. Seseorang mungkin tertanya-tanya sama ada terdapat alternatif kepada pendekatan verbose ini, serupa dengan ciri Reflection C#.
malangnya tiada mekanisme automatik
Malangnya, C tidak mempunyai mekanisme untuk objek ciptaan automatik jenis yang ditentukan pada masa jalan. Walau bagaimanapun, pemetaan boleh dilakukan sendiri:
Pemetaan jenis
Anda boleh mencipta peta yang menyimpan, untuk setiap nama kelas, fungsi yang mencipta objek daripada kelas itu:
template<typename T> Base * createInstance() { return new T; } typedef std::map<std::string, Base*(*)()> map_type; map_type map; map["DerivedA"] = &createInstance<DerivedA>; map["DerivedB"] = &createInstance<DerivedB>;
Kemudian anda boleh membuat instantiate objek juga bantuan:
return map[some_string]();
Taip pendaftaran
Penyelesaian alternatif ialah membenarkan jenis mendaftar sendiri:
// w base.hpp: template<typename T> Base * createT() { return new T; } struct BaseFactory { typedef std::map<std::string, Base*(*)()> map_type; static Base * createInstance(std::string const& s) { map_type::iterator it = getMap()->find(s); if(it == getMap()->end()) return 0; return it->second(); } protected: static map_type * getMap() { // nigdy nie usuwane (istnieje do zakończenia programu) // ponieważ nie możemy zagwarantować poprawnej kolejności usuwania if(!map) { map = new map_type; } return map; } private: static map_type * map; }; template<typename T> struct DerivedRegister : BaseFactory { DerivedRegister(std::string const& s) { getMap()->insert(std::make_pair(s, &createT<T>)); } }; // w derivedb.hpp class DerivedB { ...; private: static DerivedRegister<DerivedB> reg; }; // w derivedb.cpp: DerivedRegister<DerivedB> DerivedB::reg("DerivedB");
Anda juga boleh menentukan makro untuk pendaftaran jenis :
#define REGISTER_DEC_TYPE(NAME) \ static DerivedRegister<NAME> reg #define REGISTER_DEF_TYPE(NAME) \ DerivedRegister<NAME> NAME::reg(#NAME)
Untuk jenis yang tidak berkongsi kelas asas biasa, anda boleh menggunakan varian boost::variant sebagai jenis pemulangan fungsi:
typedef boost::variant<Foo, Bar, Baz> variant_type; template<typename T> variant_type createInstance() { return variant_type(T()); } typedef std::map<std::string, variant_type (*)()> map_type;
Atas ialah kandungan terperinci Bagaimana untuk Mencipta Objek C daripada Rentetan yang Mengandungi Nama Kelasnya?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!