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 ) );
}