• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆-341  評論-2670  文章-0  trackbacks-0
                C++的反射一直是一個(gè)很多人都在做的事情。不過今天我終于有了一個(gè)簡單的想法,當(dāng)然只對VC++編譯出來的程序有效。首先看下面的一個(gè)單元測試:

                如果我們有下面的代碼:
            1     class A{};
            2     class B:public A{};
            3     class C:public A{};
            4     class D:public B, public C{};
            5     class E:virtual public A{};
            6     class F:virtual public A{};
            7     class G:public E, public F{};
                那么下面的事情一定會發(fā)生:
            1     D d;
            2     A& da1=static_cast<B&>(d);
            3     A& da2=static_cast<C&>(d);
            4     TEST_ASSERT(&da1!=&da2);
            5     
            6     G g;
            7     A& ga1=static_cast<E&>(g);
            8     A& ga2=static_cast<F&>(g);
            9     TEST_ASSERT(&ga1==&ga2);

                對于這種virtual繼承的事情,到這里還是很容易理解的。那現(xiàn)在我們來更進(jìn)一步:
             1     class Base
             2     {
             3     public:
             4         size_t size;
             5 
             6         Base()
             7             :size(0)
             8         {
             9         }
            10     };
            11 
            12     template<typename T>
            13     class Derived : public virtual Base
            14     {
            15     public:
            16         Derived()
            17         {
            18             if(size<sizeof(T)) size=sizeof(T);
            19         }
            20     };
            21 
            22     class H : public Derived<H>{};
            23     class I : public H, public Derived<I>{};
            24     class J : public I, public Derived<J>{};

                首先,H、I和J都各自擁有自己的唯一的一個(gè)Base。J雖然繼承了Derived<H>、Derived<I>和Derived<J>,但是始終只擁有一個(gè)Base。因?yàn)锽ase是virtual繼承的。

                其次,sizeof(Derived<T>)>sizeof(Base)始終是成立的,因?yàn)锽ase的virtual繼承導(dǎo)致了Derived<T>里面至少要保存一個(gè)指向Base(或者可以用來找到Base)的指針。這個(gè)條件很重要,因?yàn)檫@導(dǎo)致了sizeof(J)>sizeof(I)這個(gè)條件是恒成立的。

                好了,那么來看J。由于C++并沒有規(guī)定多重繼承的時(shí)候,幾個(gè)父類的構(gòu)造函數(shù)的順序是什么,所以我們需要sizeof(J)>sizeof(I)這個(gè)條件。為什么呢?看Derived類的構(gòu)造函數(shù)——它之讓sizeof(T)更大的數(shù)據(jù)覆蓋Base里面的數(shù)據(jù)。

                所以我們就可以確定下面的事情:
            1     const H& h=H();
            2     const H& i=I();
            3     const H& j=J();
            4     TEST_ASSERT(h.size<i.size);
            5     TEST_ASSERT(i.size<j.size);
            6     TEST_ASSERT(h.size==sizeof(H));
            7     TEST_ASSERT(i.size==sizeof(I));
            8     TEST_ASSERT(j.size==sizeof(J));

                無論J的三個(gè)Derived<T>的構(gòu)造函數(shù)誰先執(zhí)行,最后能夠留下來的Base里面的數(shù)據(jù)肯定是Derived<J>里面的數(shù)據(jù)。講到這里應(yīng)該很清楚了。如果讀者還沒想到這跟反射有什么關(guān)系的話,那么請想一下,如果Base除了size以外,還有一個(gè)ITypeDescriptor** typeDescriptor;成員。然后Derived改成這樣:
             1 template<typename T>
             2 class Derived : 
             3 {
             4 public:
             5     static ITypeDescriptor* type;
             6 
             7     Derived()
             8     {
             9         if(){size=sizeof(T); typeDescriptor=&type;}
            10     }
            11 };

                那么不管你的J拿到手里的類型是什么,哪怕是const H& j,那么j.typeDescriptor肯定就是&Derived<J>::type;

                到這里還沒有跟VC++有關(guān)系的東西。假設(shè)ITypeDescriptor是一個(gè)足夠代表反射功能的高級接口的話,那么我們要怎么實(shí)現(xiàn)它呢?我們自己來按照字符串去調(diào)用各種函數(shù)什么的去實(shí)現(xiàn)它肯定麻煩到死了。但是如果大家還記的我前面的這篇博客文章的話,那么大家肯定想到了,我們可以寫一個(gè)程序來替我們讀pdb生成ITypeDescriptor的代碼,還有把具體的對象賦值進(jìn)Derived<T>::type里面去的一個(gè)初始化函數(shù)!啊哈哈哈!當(dāng)然pdb只能是從Visual C++編譯出來的,就算不是,也至少只能是Windows上面的。不過對GacUI來說并無所謂。因?yàn)槲抑灰袵acUI在VisualStudio里面編譯生成反射的代碼,這個(gè)生成之后的代碼我還是能放到其他地方編譯的。到時(shí)候我只要連同這段代碼一并發(fā)布就好了。

                當(dāng)然,這個(gè)程序不僅僅可以幫我實(shí)現(xiàn)ITypeDescriptor,還可以幫我實(shí)現(xiàn)C語言和C++語言的dll接口的實(shí)現(xiàn),因?yàn)閐ll里面肯定不能暴露模板的。下面就僅需要我去把它做出來就可以了。至此,我們讓一個(gè)類支持反射的代價(jià)很低——只要讓他繼承自Derived<自己>就好了。
            posted on 2012-01-11 03:39 陳梓瀚(vczh) 閱讀(8799) 評論(7)  編輯 收藏 引用 所屬分類: C++GacUI

            評論:
            # re: C++反射實(shí)現(xiàn)方法設(shè)想(GacUI) 2012-01-11 03:42 | ArthasLee
            發(fā)現(xiàn)文章內(nèi)容是亮點(diǎn),title的Gac更加是亮瞎我~  回復(fù)  更多評論
              
            # re: C++反射實(shí)現(xiàn)方法設(shè)想(GacUI) 2012-01-11 22:11 | 7531
            關(guān)鍵是元數(shù)據(jù)的問題,C++缺少從代碼中提取出元數(shù)據(jù)(類型信息),有了類型信息,就可以實(shí)現(xiàn)通用的自動化方法。  回復(fù)  更多評論
              
            # re: C++反射實(shí)現(xiàn)方法設(shè)想(GacUI) 2012-01-11 22:48 | 陳梓瀚(vczh)
            @7531
            pdb里面的信息足以用來生成一個(gè)不帶有template聲明的頭文件。這里面的信息是十分足夠的,你可以運(yùn)行我文章里面的那個(gè)鏈接指向的demo,來查看我提取出來的結(jié)果。

            不過,C++并不需要在運(yùn)行時(shí)讀取這些信息,完全可以寫一個(gè)程序讀pdb里面的“元數(shù)據(jù)”,為每一個(gè)函數(shù)生成一個(gè)反射的wrapper,這就足夠了。  回復(fù)  更多評論
              
            # re: C++反射實(shí)現(xiàn)方法設(shè)想(GacUI) 2012-01-12 08:00 | Scan
            老大,這事就等你拉!
            我之前考慮過根據(jù)ctags的輸出信息來對每個(gè)類生成一個(gè)描述類型,以支持反射,但是ctags的輸出又亂又雜...就覺得掃描c++源碼,生成描述類型的任務(wù),得懂編譯原理才行。
            原來即使是你,掃描c++源碼生成類型信息,也是件比較麻煩的事?  回復(fù)  更多評論
              
            # re: C++反射實(shí)現(xiàn)方法設(shè)想(GacUI) 2012-01-12 08:26 | 陳梓瀚(vczh)
            @Scan
            你說非要動真格掃描的話,麻煩雖然麻煩,但還是能做的。只是放在這種“為了反射生成代碼”的事情上面,這個(gè)就太劃不來了啊,明明有了pdb,何苦自己算一遍呢。

            當(dāng)然另一個(gè)原因是,我已經(jīng)熟悉了模板元編程了,所以我的代碼里面免不了有復(fù)雜的模板推導(dǎo),實(shí)現(xiàn)這個(gè)的確是困難的。  回復(fù)  更多評論
              
            # re: C++反射實(shí)現(xiàn)方法設(shè)想(GacUI) 2012-01-13 18:26 | ooseven
            c++下還沒有優(yōu)秀的,小型的類wpf gui框架,就等你了!  回復(fù)  更多評論
              
            # re: C++反射實(shí)現(xiàn)方法設(shè)想(GacUI) 2014-07-20 05:54 | qicosmos
            其實(shí)我還想到了一種可行的方法,通過tuple把類的元信息返回出去,返回出去之后就可以通過變參來做自己想做的事情了。  回復(fù)  更多評論
              
            国产ww久久久久久久久久| 久久久午夜精品| 久久综合综合久久综合| 欧美一级久久久久久久大片| 国产成人久久精品麻豆一区| 91久久九九无码成人网站 | 日韩欧美亚洲综合久久影院d3| 久久亚洲私人国产精品vA| 精品久久久无码人妻中文字幕 | 亚洲日本久久久午夜精品| 国内精品久久久久久久coent| 国产精品久久影院| 久久久久人妻精品一区二区三区| 亚洲一区精品伊人久久伊人| 青青草原综合久久大伊人导航 | 国产精品美女久久久久av爽| 亚洲国产精品婷婷久久| 久久99精品国产麻豆不卡| 国产免费福利体检区久久| 亚洲午夜无码久久久久小说| 国产精品久久新婚兰兰| 国内精品九九久久久精品| 99久久精品久久久久久清纯| 中文成人久久久久影院免费观看 | 久久国产精品99精品国产| 香港aa三级久久三级| 久久婷婷五月综合国产尤物app | www.久久热| 亚洲国产视频久久| 99久久免费国产精品热| 亚洲人成无码久久电影网站| 人人狠狠综合久久亚洲婷婷| 久久精品卫校国产小美女| 狠狠色丁香久久婷婷综合五月| 久久高潮一级毛片免费| 久久人做人爽一区二区三区| 国产香蕉97碰碰久久人人| 日韩亚洲国产综合久久久| 久久婷婷国产综合精品| 午夜精品久久久久9999高清| 久久九九亚洲精品|