C++ C+中的最小反射+;

C++ C+中的最小反射+;,c++,reflection,C++,Reflection,我想创建一个类工厂,我想使用反射。我只是需要 使用给定的字符串创建一个对象,并只调用少数已知的方法 我怎么能做到呢?你必须自己动手。通常,您有一个字符串到对象创建函数的映射。 您将需要以下内容: class thing {...}; /* class thing_A : public thing {...}; class thing_B : public thing {...}; class thing_C : public thing {...}; */ std::shared_ptr<

我想创建一个类工厂,我想使用反射。我只是需要 使用给定的字符串创建一个对象,并只调用少数已知的方法


我怎么能做到呢?

你必须自己动手。通常,您有一个字符串到对象创建函数的映射。
您将需要以下内容:

class thing {...};
/*
class thing_A : public thing {...};
class thing_B : public thing {...};
class thing_C : public thing {...};
*/

std::shared_ptr<thing> create_thing_A(); 
std::shared_ptr<thing> create_thing_C(); 
std::shared_ptr<thing> create_thing_D();

namespace {
  typedef std::shared_ptr<thing> (*create_func)();

  typedef std::map<std::string,create_func> creation_map;
  typedef creation_map::value_type creation_map_entry;
  const creation_map_entry creation_map_entries[] = { {"A", create_thing_A}
                                                    , {"B", create_thing_B}
                                                    , {"C", create_thing_C} };
  const creation_map creation_funcs( 
          creation_map_entries, 
          creation_map_entries + sizeof(creation_map_entries)
                               / sizeof(creation_map_entries[0] );
}

std::shared_ptr<thing> create_thing(const std::string& type)
{
  const creation_ma::const_iterator it = creation_map.find(type);
  if( it == creation_map.end() ) {
     throw "Dooh!"; // or return NULL or whatever suits you
  }
  return it->second();
}
类事物{…};
/*
类事物A:公共事物{…};
类事物:公共事物{…};
类事物C:公共事物{…};
*/
std::shared_ptr create_thing_A();
std::shared_ptr create_thing_C();
std::shared_ptr create_thing_D();
名称空间{
typedef std::shared_ptr(*create_func)();
typedef std::地图创建\地图;
typedef创建\映射::值\类型创建\映射\条目;
const creation_map_entry creation_map_entries[]={{“A”,create_thing_A}
,{“B”,创建东西{B}
,{“C”,创建{u thing};
常量创建\映射创建\函数(
创建映射项,
创建映射项+大小(创建映射项)
/sizeof(创建映射项[0]);
}
std::shared_ptr create_thing(const std::string&type)
{
const creation\u ma::const\u迭代器it=creation\u map.find(type);
if(it==creation\u map.end()){
抛出“Dooh!”//或返回NULL或任何适合您的值
}
返回它->秒();
}

还有其他方法(如拥有),但是我认为它们都归结为有一个字符串映射到与特定类型相关的东西。

< P>没有C++中的反射,直接支持标准。< /P> < C++ >足够低的级别,可以实现对反射的一些最小支持,以完成手头的任务。

对于创建工厂的简单任务,通常使用
Prototype
方法:

class Base
{
public:
  virtual Base* clone() const = 0;
  virtual ~Base();
};

class Factory
{
public:
  std::unique_ptr<Base> get(std::string const& name);

  void set(std::string const& name, std::unique_ptr<Base> b);

private:
  boost::ptr_map<std::string,Base> mExemplars;
};
类基
{
公众:
虚拟基*clone()常量=0;
虚拟~Base();
};
阶级工厂
{
公众:
std::unique_ptr get(std::string const&name);
无效集(std::string const&name,std::unique_ptr b);
私人:
boost::ptr_映射mExemplars;
};

当然,你所说的那些“已知方法”应该在 Base<代码>类中定义,作为接口。

< P>在C++中没有反射,所以你应该重新陈述你的问题,试图用它的反射部分解释你将满足什么要求。 根据您的实际约束和要求,您可以做一些事情。我将采取的第一种方法是创建一个抽象工厂,具体工厂可以在其中注册并提供一个简单的接口:

class Base {}; // shared base by all created objects
class ConcreteFactoryBase {
public:
   virtual ~ConcreteFactoryBase() {}
   virtual Base* create() const = 0;   // actual construction
   virtual std::string id() const = 0; // id of the types returned
};
class AbstractFactory
{
   typedef std::map<std::string, ConcreteFactory* > factory_map_t;
public:
   void registerFactory( ConcreteFactoryBase* factory ) {
      factories[ factory->id() ] = factory;
   }
   Base* create( std::string const & id ) const {
      factory_map_t::const_iterator it = factories.find( id );
      if ( it == factories.end() ) {
         return 0; // or throw, or whatever makes sense in your case
      }
      return (*it)->create();
   }
   ~AbstractFactory(); // ensure that the concrete factories are deleted
private:
   std::map<ConcreteFactoryBase*> factories;
};
class Base{};//由所有创建的对象共享的Base
类ConcreteFactoryBase{
公众:
虚拟~ConcreteFactoryBase(){}
虚拟基*create()常量=0;//实际构造
virtual std::string id()const=0;//返回的类型的id
};
类抽象工厂
{
typedef std::映射工厂映射;
公众:
无效注册表工厂(ConcreteFactoryBase*工厂){
工厂[工厂->id()]=工厂;
}
基本*创建(标准::字符串常量和id)常量{
factory\u map\u t::const\u迭代器it=factories.find(id);
if(it==factories.end()){
返回0;//或抛出,或在您的情况下有意义的任何内容
}
return(*it)->create();
}
~AbstractFactory();//确保删除具体工厂
私人:
地图工厂;
};
实际的混凝土工厂可以手动实现,但它们可能可以模板化,除非不同类型的构造函数需要不同的参数:

template <typename T>
class ConcreteFactory : public ConcreteFactoryBase {
public:
   ConcreteFactory( std::string const & id ) : myid(id) {}
   virtual Base* create() const {
      return new T;
   }
   virtual std::string id() const {
      return myid;
   }
private:
   std::string myid;
};
class Test : public Base {};
int main() {
   AbstracFactory factory;
   factory.register_factory( new ConcreteFactory<Test>("Test") );
}
模板
类别ConcreteFactory:公共ConcreteFactoryBase{
公众:
混凝土工厂(std::string const&id):myid(id){}
虚拟基*create()常量{
返回新的T;
}
虚拟std::字符串id()常量{
返回myid;
}
私人:
std::字符串myid;
};
类测试:公共基{};
int main(){
艾布拉克工厂;
工厂。注册工厂(新混凝土工厂(“测试”);
}
或者,您可以调整签名,以便可以通过不同的层将参数传递给构造函数


同样,通过了解实际约束,其他一些方法可能会更好。其他地方建议的
clone()
方法是好的(通过实际克隆或创建相同类型的空对象)。这基本上是将工厂与对象本身混合在一起,使每个对象都是相同类型对象的工厂。我不太喜欢将这两种职责混合在一起,但这可能是最简单的方法之一,只需编写更少的代码。

您可以使用typeid和模板来实现工厂,这样您就不需要字符串了全部

#include <string>
#include <map>
#include <typeinfo>

//***** Base *****
class Base
{
public:
    virtual ~Base(){} //needs to be virtual to make typeid work
};

//***** C1 *****
class C1 : public Base
{};

//***** Factory *****
class Factory
{
public:
    template <class T>
    Base& get();
private:
    typedef std::map<std::string, Base> BaseMap;
    BaseMap m_Instances;
};

template <class T>
Base& Factory::get()
{
    BaseMap::const_iterator i = m_Instances.find(typeid(T).name());
    if(i == m_Instances.end()) {
       m_Instances[typeid(T).name()] = T();
    }
    return m_Instances[typeid(T).name()];
}

//***** main *****
int main(int argc, char *argv[])
{
    Factory f;
    Base& c1 = f.get<C1>();
    return 0;
}
#包括
#包括
#包括
//*****基地*****
阶级基础
{
公众:
virtual~Base(){}//需要是虚拟的才能使typeid工作
};
//*****C1*****
C1类:公共基地
{};
//*****工厂*****
阶级工厂
{
公众:
模板
Base&get();
私人:
typedef std::map BaseMap;
基本映射m_实例;
};
模板
基本和工厂::get()
{
BaseMap::const_iterator i=m_Instances.find(typeid(T).name());
if(i==m_Instances.end()){
m_实例[typeid(T).name()]=T();
}
返回m_实例[typeid(T).name()];
}
//*****主要*****
int main(int argc,char*argv[])
{
f厂;
Base&c1=f.get();
返回0;
}

<代码> >你能提供你实际期望的伪代码吗?这里没有办法帮助你。C++中的反射是什么样子的?”Gabe:C++中没有反射,有不同的方法来模拟反射,但是它不是语言提供的。++,当然,可行的是C++是多范式和强大的。是的,克隆