Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;动态类(动态黑客)_C++_Dynamic - Fatal编程技术网

C++ C++;动态类(动态黑客)

C++ C++;动态类(动态黑客),c++,dynamic,C++,Dynamic,有没有办法在运行时将字段添加到类中(以前不存在的字段)?类似于以下片段: Myobject *ob; // create an object ob->addField("newField",44); // we add the field to the class and we assign an initial value to it printf("%d",ob->newField); // now we can access that field 我真的不在乎怎么做,我不在乎

有没有办法在运行时将字段添加到类中(以前不存在的字段)?类似于以下片段:

Myobject *ob; // create an object
ob->addField("newField",44); // we add the field to the class and we assign an initial value to it
printf("%d",ob->newField); // now we can access that field
我真的不在乎怎么做,我不在乎这是不是一个丑陋的黑客,我想知道它是否可以做到,一个小例子,如果可能的话

另一个示例:假设我有一个描述此类的XML文件:

<class name="MyClass">
   <member name="field1" />
   <member name="field2" />
</class>
我不想在运行时创建类,我只想向现有类添加成员/字段


谢谢大家!

没有办法按照您描述的方式执行,因为编译器需要在编译时解析引用-它将生成错误


但是,

不——C++不支持对这样的类型系统的任何操作。即使是具有某种程度的运行时反射的语言(例如.NET)也不完全支持这种范式。您需要一种更具动态性的语言才能做到这一点。

简短版本:无法做到。没有本地支持,C++是静态类型的,编译器必须知道每个对象的结构。 建议:使用嵌入式对讲机。不要写你自己的(见下文),找一个已经运行并调试过的


您可以做什么:根据您的需要实施足够的interperter

将类设置为数据成员(如

std::vector<void*> extra_data;

但这并不是限制,只要稍微小心一点,您就可以将任意数据与名称关联起来,并且您可以根据自己的意愿继续详细阐述此方案(添加类型信息等),但归根结底,这就是实现一个interperter来照顾您的运行时灵活性。

您无法使用这种语法(因为在编译时进行静态检查),但是如果您愿意修改语法,就可以很容易地达到相同的效果。使用string->blob映射的字典成员以及如下成员函数将非常容易:

template< typename T > T get_member( string name );
template< typename T > void set_member( string name, T value );
templateT get_成员(字符串名);
模板无效集\成员(字符串名称,T值);
如果您愿意,您可以使语法更加紧凑/复杂(例如:使用'->'运算符重写)。您还可以利用一些编译器特有的技巧(例如,MSVC支持_declspec(属性),它允许您将对成员变量的引用映射到特定格式的方法)。但是,到最后,您将无法在该语言中执行编译器不接受的操作并使其进行编译。

使用映射和变体。 例如,使用boost::variant

(当然,您可以创建自己的,以适应XML属性的类型。)

#包括
#包括
typedef boost::variantMyValue;
typedef std::map MyValueMap;
通过将MyValueMap添加为类的成员,可以根据属性的名称添加属性。这意味着代码:

oMyValueMap.insert(std::make_pair("newField", 44)) ;
oMyValueMap.insert(std::make_pair("newField2", "Hello World")) ;
std::cout << oMyValueMap["newField"] ;
std::cout << oMyValueMap["newField2"] ;
插入(std::make_pair(“newField”,44)); 插入(std::make_pair(“newField2”,“Hello World”);
std::cout我正在看这个,我做了一些搜索,这段代码片段来自: 使用

首先定义一个结构,该结构定义一个包含键(即变量名)和值的std::map。定义一个函数来对该对进行ad,并将其与一个函数一起设置以获取值。如果你问我,这很简单,但在做更复杂的事情之前,这似乎是一个开始的好方法

struct AnyMap {
  void addAnyPair( const std::string& key , boost::any& value );

  template<typename T>
  T& get( const std::string key ) {
    return( boost::any_cast<T&>(map_[key]) );
  }

  std::map<const std::string, boost::any> map_;
};

void AnyMap::addAnyPair( const std::string& key , boost::any& value ) {
  map_.insert( std::make_pair( key, value ) );
}
struct AnyMap{
void addAnyPair(const std::string和key,boost::any和value);
模板
T&get(常量标准::字符串键){
return(boost::any_cast(map_[key]);
}
std::map;
};
void AnyMap::addAnyPair(const std::string和key,boost::any和value){
映射插入(std::make_对(键、值));
}

底线,这是一个黑客攻击,因为C++是严格的类型检查语言,因此怪物在规则的范围内。< /P>编辑你的问题,使内容正确显示……-谢谢你!是否可以重载->以达到我所说的效果?不,抱歉,因为您添加的“newField”尚未编译,仅在运行时创建,因此,它不能用于代码符号,只能用于字符串(尽管存在一些缺点,但操作符[]是一个闪亮的语法糖)@vhaerun在->之后您会键入什么?如果你知道答案,你不需要在运行时添加变量@我不明白你为什么认为后者会失去类型安全性。它比使用变型器安全,是吗?”@穆:我写的“你失去了某种类型的C++安全”,我确实暗示:“[通过使用变体]你失去了某种类型的C++安全性”,帕尔塞巴的答案是相似的,并且使用更多的C++习语。我的看起来很像是一个塞进类中的解决方案,因为它就是这样的……我认为模板在编译后就完成了。因此,我不知道这段代码如何在类中生成运行时成员,例如,给定输入,向类添加变量。这不是可以通过模板实现的。也许,我没有得到你的答案,所以我不投反对票。我只是好奇你在想什么。@G24l:我假设这是一个类,它包装了一个变量映射,在这种情况下,它编译得很好

#include <map>
#include <boost/variant.hpp>

typedef boost::variant< int, std::string > MyValue ;
typedef std::map<std::string, MyValue> MyValueMap ;
oMyValueMap.insert(std::make_pair("newField", 44)) ;
oMyValueMap.insert(std::make_pair("newField2", "Hello World")) ;
std::cout << oMyValueMap["newField"] ;
std::cout << oMyValueMap["newField2"] ;
oMyObject.addField("newField", 44) ;
oMyObject.addField("newField2", "Hello World") ;
std::cout << oMyObject["newField"] ;
std::cout << oMyObject["newField2"] ;
struct AnyMap {
  void addAnyPair( const std::string& key , boost::any& value );

  template<typename T>
  T& get( const std::string key ) {
    return( boost::any_cast<T&>(map_[key]) );
  }

  std::map<const std::string, boost::any> map_;
};

void AnyMap::addAnyPair( const std::string& key , boost::any& value ) {
  map_.insert( std::make_pair( key, value ) );
}