java反射头文件_编程基础知识——C++能不能支持Java和ObjC的反射?
C++能不能支持Java和ObjC的反射?
要回答這個(gè)問題。首先我們要清楚什么是反射。什么是反射?
教科書的解釋我就不說了,(^o^)事實(shí)上我也記不得。實(shí)際開發(fā)應(yīng)用的反射就是在沒有某個(gè)類型的頭文件或者類結(jié)構(gòu)定義的情況下,存取這個(gè)類型的對(duì)象的成員字段的值。調(diào)用這個(gè)對(duì)象的成員函數(shù)(方法)。
比方我有定義了一個(gè)類型 Class ?A,里面有 a,b,c三個(gè)字段,有fun()函數(shù)。
如今我手里僅僅有一個(gè) void* pA,注意它的類型僅僅是一個(gè)void指針,我手里也沒有Class的頭文件。我要怎么樣得到,a,b。c的值呢?怎么調(diào)用fun函數(shù)呢?另一種需求就是通過字符串運(yùn)行代碼。比方已經(jīng)拿到了一A的對(duì)象pA了,還拿到了一個(gè)字符串 "pA->fun()",如今怎么樣才干將這個(gè)字符串代表的代碼。運(yùn)行了呢?(后面這樣的需求最典型的需求就是表達(dá)式引擎)。以上說的就是反射的用處和優(yōu)點(diǎn),非常多實(shí)際需求中使用起來是非常非常方便的,能夠在非常多場合節(jié)省非常多時(shí)間,少寫非常多代碼。
眾所周知。Java和ObjC支持反射。當(dāng)然還有其它語言也支持,本人知識(shí)水平有限。不能全然列舉還請(qǐng)見諒。
假設(shè)要實(shí)現(xiàn)反射,就須要實(shí)現(xiàn)例如以下幾個(gè)功能:
拿到一個(gè)對(duì)象指針。哪怕它是void。也能通過一些API,得到它的真實(shí)類類型名稱。比方j(luò)ava能夠得到它的實(shí)際類型的包路徑+類名
拿到這個(gè)對(duì)象指針,還能得到它全部的成員變量。成員函數(shù)的名稱,類型(字段),參數(shù)和返回類型(函數(shù)),以字符串或者其它封裝類型返回。核心還是字符串。
拿到這個(gè)對(duì)象指針,能夠通過字符串。運(yùn)行某個(gè)函數(shù)。能夠通過字符串,取得某個(gè)成員的值。
Java和ObjC都能支持反射,另一個(gè)前提是由于他們都統(tǒng)一基類。比方j(luò)ava里叫 java.lang.Object 。ObjC里面是 NSObject。有了統(tǒng)一基類,才可以預(yù)先定義一套反射的機(jī)制和API。不論什么繼承這個(gè)基類的實(shí)現(xiàn)類,都附帶贈(zèng)送了早已實(shí)現(xiàn)的反射功能。
而C++沒有標(biāo)準(zhǔn)基類,各種框架,各種平臺(tái)有各種各樣的框架,類庫。
如果我們自己在實(shí)際開發(fā)的系統(tǒng)里面,定義一個(gè)統(tǒng)一基類,是不是能在C++里面。實(shí)現(xiàn)反射功能,哪怕是別扭的實(shí)現(xiàn)也好啊,這樣也能夠降低非常多苦逼C++開發(fā)者的工作量的呀,多好的事啊。
試試吧
首先我們?nèi)绻麘?yīng)用程序里面的全部類。都有一個(gè)公共基類。
其次C++里面的成員變量,成員函數(shù),對(duì)象,全部一切,都是指針定位。
所以我們先要解決,通過“一個(gè)對(duì)象指針 + 一個(gè)函數(shù)指針調(diào)用函數(shù)的問題”。
完整演示程序已經(jīng)寫好了
#include "stdafx.h"
class CXObject
{
public:
int doSum(int a, int b);
};
typedef int (CXObject::*pf_doSum)(int, int);
int CXObject::doSum(int a, int b)
{
return a + b ;
}
void dosome(CXObject* pObj, pf_doSum func)
{
int result = (pObj->*func)(100, 23);
printf("result=%d", result);
}
int _tmain(int argc, _TCHAR* argv[])
{
CXObject obj ;
dosome(&obj, &CXObject::doSum);
getchar();
return 0;
}
能夠看到,能夠通過一個(gè)對(duì)象指針,加一個(gè)函數(shù)指針 調(diào)用函數(shù)。
這是C++里面也算是非經(jīng)常常使用的技巧了。
MFC里面系統(tǒng)生成的代碼非常多都是用這樣的方式。
我們的需求是通過字符串,調(diào)用函數(shù),所以就須要建立一個(gè) 函數(shù)名稱 到 函數(shù)指針的映射關(guān)系。然后就能夠字符串查找 函數(shù)指針,函數(shù)指針調(diào)用函數(shù)了。
請(qǐng)看完整代碼:
// test01.cpp : 定義控制臺(tái)應(yīng)用程序的入口點(diǎn)。
//
#include "stdafx.h"
#include
#include
class CXObject ;
typedef void (CXObject::*void_func_void)(void);
class CXObject
{
public:
//取得類的全部函數(shù)的名稱
virtual void getMethodNames(std::vector<:string>& names);
//依據(jù)名稱,取得函數(shù)指針
virtual void_func_void getFuncByName(std::string& name);
};
void CXObject::getMethodNames(std::vector<:string>& names){}
void_func_void CXObject::getFuncByName(std::string& name){return NULL;}
class CXMyImpl : public CXObject
{
public: //須要實(shí)現(xiàn)的函數(shù)
//取得類的全部函數(shù)的名稱
virtual void getMethodNames(std::vector<:string>& names);
//依據(jù)名稱,取得函數(shù)指針
virtual void_func_void getFuncByName(std::string& name);
public://自定義的業(yè)務(wù)函數(shù)。
void doPrint1();
void doPrint2();
};
void CXMyImpl::getMethodNames(std::vector<:string>& names)
{
names.push_back("doPrint1");
names.push_back("doPrint2");
}
void_func_void CXMyImpl::getFuncByName(std::string& name)
{
void_func_void pFun = NULL ;
if(name.compare("doPrint1") == 0)
pFun = static_cast(&CXMyImpl::doPrint1) ;
if(name.compare("doPrint2") == 0)
pFun = static_cast(&CXMyImpl::doPrint2) ;
return pFun ;
}
void CXMyImpl::doPrint1()
{
printf("CXMyImpl::doPrint1 be called!!\r\n");
}
void CXMyImpl::doPrint2()
{
printf("CXMyImpl::doPrint2 be called!!\r\n");
}
int _tmain(int argc, _TCHAR* argv[])
{
CXObject* obj = new CXMyImpl();
//后面的代碼里,并沒有CXMyImpl,CXObject里面未定義doPrint1,doPrint2.
//通過字符串的doPrint1運(yùn)行doPrint1函數(shù)。
std::vector<:string> names ;
obj->getMethodNames(names);
for(int idx=0; idx
{
void_func_void pfun = obj->getFuncByName(names[idx]);
(obj->*pfun)();
}
getchar();
return 0;
}
執(zhí)行結(jié)果例如以下:
從上面的樣例能夠看到,事實(shí)上是能夠模擬出反射的效果的。
假設(shè)要C++全然的實(shí)現(xiàn)方便有用的反射機(jī)制,須要下面幾點(diǎn)條件:
1、統(tǒng)一的基類
2、編譯器要幫忙
對(duì)于第二條條件,能夠這樣理解:
在上樣例中
void CXMyImpl::getMethodNames(std::vector<:string>& names)
{
names.push_back("doPrint1");
names.push_back("doPrint2");
}
void_func_void CXMyImpl::getFuncByName(std::string& name)
{
void_func_void pFun = NULL ;
if(name.compare("doPrint1") == 0)
pFun = static_cast(&CXMyImpl::doPrint1) ;
if(name.compare("doPrint2") == 0)
pFun = static_cast(&CXMyImpl::doPrint2) ;
return pFun ;
}
這兩個(gè)函數(shù)是基類里面定義好了的,算是反射相關(guān)的API,可是假設(shè)我每寫一個(gè)類都要自己實(shí)現(xiàn)這兩個(gè)函數(shù)。那豈不是要累死。
可是反過來看,這兩個(gè)函數(shù)的功能很easy,代碼很有規(guī)律。那就是記錄當(dāng)前的類有那些函數(shù),把名字和函數(shù)指針相應(yīng)起來。這個(gè)過程全然能夠讓編譯器在編譯的時(shí)候自己主動(dòng)為我加上。
還有一方面,因?yàn)闉榱朔奖阊菔尽_@里面用到的業(yè)務(wù)函數(shù)都是 void f(void)類型的。沒有參數(shù)和返回值,這樣顯然是不合理的。可是并非不能實(shí)現(xiàn),僅僅只是那樣更復(fù)雜。繞的圈子很多其它。
在沒有這種編譯器出現(xiàn),在沒有這種統(tǒng)一基類的類庫的情況下,C++的反射,僅僅是停留在興趣調(diào)研的階段,眼下沒看到什么實(shí)際價(jià)值。個(gè)人感覺的哈。
總結(jié)
以上是生活随笔為你收集整理的java反射头文件_编程基础知识——C++能不能支持Java和ObjC的反射?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 谷歌浏览器开发调试工具中Sources面
- 下一篇: JSP+Javabean+Servlet