本发明涉及c++技术领域,特别是涉及一种在c++程序中实现反射的方法、存储介质及计算设备。
背景技术:
反射是程序可以访问、检测和修改其本身状态或行为的一种能力。很多语言都支持反射,有了反射,就能够让代码具有自省能力,让代码知道自己能够做什么。反射适用于如下场合:
1)序列化和数据绑定;2)数据驱动,通过字符串就能够创建出类实例,通过字符串就能够访问类方法和类属性。
目前java、c#等高级语言都支持反射,能否通过反射来动态获取类信息已经成为现代软件的标志之一,而c++目前是不支持反射功能的。现有技术中,在c++程序中支持反射的一种实现方式为:解析调试信息,例如,visualstudio开发的程序,可以通过解析pdb文件获得调试信息,此种实现方式的优点在于不需要修改代码,缺点则在于必须要编译器相关的调试信息。
技术实现要素:
为了解决现有技术存在的不足,本发明的目的在于提供一种在c++程序中实现反射的方法、存储介质及计算设备,可以使c++项目支持反射,从而实现ue4的蓝图功能,进而极大地简化编辑器开发。
为实现上述目的,本发明提供的在c++程序中实现反射的方法,包括以下步骤:
创建c++类的反射类,所述反射类用以保存c++类的反射信息;
用宏来封装c++类的反射类,以及访问c++类的反射类中保存的c++类的反射信息。
进一步地,所述c++类的反射信息包括:c++类的属性和函数的反射信息。
进一步地,所述创建c++类的反射类的步骤是,在c++类的代码中添加预设的标志位,获得c++类的反射信息,创建c++类的反射类。
所述获得c++类的反射信息的步骤进一步包括步骤:
为c++类的每个属性分别设置对应的get和set函数,在c++类的反射信息中保存get和set函数指针,其中,所述get和set函数分别用于获取和设置c++类的属性。
所述get函数进一步用于记录c++类的属性的名字。
所述获得c++类的反射信息的步骤进一步包括步骤:
通过模板推导,记录c++类的函数的反射信息,其中,所述c++类的函数的反射信息,包括:函数参数个数、每个参数的数据类型、函数是否为静态函数、函数的返回值数据类型和函数指针。
进一步地,所述的在c++程序中实现反射的方法,还包括步骤:通过将第三方类序列化成字符串的方式,将第三方类转换为c++类的成员变量和函数参数。
所述用宏来封装c++类的反射类的步骤进一步包括步骤:用宏在c++类中,注册c++类的反射类,以及c++类的反射类中保存的c++类的反射信息。
为实现上述目的,本发明提供的计算机可读存储介质,其上存储有计算机程序,该程序被处理器执行时实现本发明任一项所述方法的步骤。
为实现上述目的,本发明提供的计算设备,包括存储器、处理器及存储在存储器上并可在处理器上运行的计算机程序,所述处理器执行所述程序时实现本发明任一项所述方法的步骤。
本发明的在c++程序中实现反射的方法、存储介质及计算设备,可以使c++项目支持反射,实现ue4的蓝图功能,极大地简化编辑器开发。
本发明的其它特征和优点将在随后的说明书中阐述,并且,部分地从说明书中变得显而易见,或者通过实施本发明而了解。
附图说明
附图用来提供对本发明的进一步理解,并且构成说明书的一部分,并与本发明的实施例一起,用于解释本发明,并不构成对本发明的限制。在附图中:
图1为根据本发明的在c++程序中实现反射的方法流程图。
具体实施方式
以下结合附图对本发明的优选实施例进行说明,应当理解,此处所描述的优选实施例仅用于说明和解释本发明,并不用于限定本发明。
图1为根据本发明的在c++程序中实现反射的方法流程图,下面将参考图1,对本发明的在c++程序中实现反射的方法进行详细描述。
在步骤110,创建c++类的反射类,c++类的反射类用以保存c++类的属性、函数(方法)等的反射信息。
该步骤中,在c++类的代码中添加预设的标志位,获得c++类的反射信息。例如,在qt、ue4的c++类中,在需要反射的函数、方法前面添加预设的标志位,获得c++类的反射信息。
具体而言,为c++类的每个属性分别设置对应的get和set函数,在c++类的反射信息中保存get和set函数指针,其中,get和set函数分别用于获取和设置c++类的属性。如程序1-1所示,通过函数指针,记录c++类的属性的名字,获取c++类的属性的设置功能。
程序1-1
classtest
{
public:
voidfunc(){}
intgetflag(){returnm_nflag;}
voidsetflag(intnflag){m_nflag=nflag;}
private:
intm_nflag;
};
以及通过模板推导,记录c++类的函数(方法)的反射信息,其中,记录的反射信息包括:函数参数个数、每个参数的数据类型、函数是否为静态函数、函数的返回值数据类型和函数指针等。如程序1-2所示,利用模板来自动推导c++类的函数参数,因此只需要注册函数名,例如代码:reg_func(test,func);
程序1-2(1-1续)
reg(test);
reg_field(int,test,m_nflag,getflag,setflag);
reg_func(test,func);
通过模板推导,获得c++类的函数(方法)的反射信息时,如程序1-3所示,首先利用模板特化,让编译器自动匹配参数一致的函数。程序1-3为一个参数的模板偏特化的例子,并且为了避免void*,统一使用任意变量var来存储数据。
程序1-3
template<class__rt,class__c,class__p1>
inlinemethodtype*rttifunctypeof(__rt(__c::*f)(__p1)){
returnnewrttifunctype1<__rt,__c,__p1>(f);
}
template<class__rt,class__c,class__p1>
classrttifunctype1:publicmethodtype
{
public:
typedef__rt(__c::*fptr)(__p1);
fptrf;
rttifunctype1(fptrf)
{
//记录必须的反射信息:函数指针、返回值类型、参数个数、各个参数的类型
this->f=f;
m_nreturntype=tvartraits<__rt>::type;
intnparamtype=tvartraits<__p1>::type;
m_paramstype.push_back(nparamtype);
}
virtualvoidinvoke(void*obj,constivarlist&args,ivarlist&res){
//提取函数调用参数
__p1p1=tvargetter<__p1>::get(args,0);
//通过反射信息中记录的函数指针来调用函数
tvarsetter<__rt>::set(res,(((__c*)obj)->*f)(p1));
//res<<(((__c*)obj)->*f)(p1);
}
};
上述步骤,采用了非侵入式的方式获取了c++类的反射信息,从而能够使现有c++项目中的第三方库也支持反射。
对于现有的c++项目中的第三方类,将第三方类序列化成字符串,即可实现将第三方类转换为c++类成员变量和函数参数,如程序1-4所示。
程序1-4
template<>
structtvargetter<constoc::fvector&>
{
staticoc::fvectorget(constivar&v)
{
oc::fvectortemp;
temp.parsefrom(v.stringval());
returntemp;
}
staticoc::fvectorget(constivarlist&vl,size_tindex)
{
returntvargetter<oc::fvector>::get(vl,index);
}
};
在步骤120,用宏来封装c++类的反射类,以及访问c++类的反射类中保存c++类的属性、函数(方法)等的反射信息。
该步骤中,用宏在c++类中,注册c++类的反射类以及c++类的反射类中保存的需要反射的c++类的属性和函数(方法)等的反射信息。
基于本发明的在c++程序中实现反射的方法,本发明提供的计算机可读存储介质,其上存储有计算机程序,该程序被处理器执行时实现本发明所述方法的步骤。
本发明提供的计算机可读存储介质,可位于一个或者多个计算设备,所述计算设备包括处理器,所述处理器执行其所在计算设备上的所述计算机可读存储介质中的计算机程序,实现本发明所述方法的步骤。
本发明的在c++程序中实现反射的方法、存储介质及计算设备,可以使c++项目支持反射,实现ue4的蓝图功能,极大地简化编辑器开发。
本领域普通技术人员可以理解:以上所述仅为本发明的优选实施例而已,并不用于限制本发明,尽管参照前述实施例对本发明进行了详细的说明,对于本领域的技术人员来说,其依然可以对前述各实施例记载的技术方案进行修改,或者对其中部分技术特征进行等同替换。凡在本发明的精神和原则之内,所作的任何修改、等同替换、改进等,均应包含在本发明的保护范围之内。