• <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++的反射一直是一個很多人都在做的事情。不過今天我終于有了一個簡單的想法,當然只對VC++編譯出來的程序有效。首先看下面的一個單元測試:

                如果我們有下面的代碼:
            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{};
                那么下面的事情一定會發生:
            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繼承的事情,到這里還是很容易理解的。那現在我們來更進一步:
             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都各自擁有自己的唯一的一個Base。J雖然繼承了Derived<H>、Derived<I>和Derived<J>,但是始終只擁有一個Base。因為Base是virtual繼承的。

                其次,sizeof(Derived<T>)>sizeof(Base)始終是成立的,因為Base的virtual繼承導致了Derived<T>里面至少要保存一個指向Base(或者可以用來找到Base)的指針。這個條件很重要,因為這導致了sizeof(J)>sizeof(I)這個條件是恒成立的。

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

                所以我們就可以確定下面的事情:
            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的三個Derived<T>的構造函數誰先執行,最后能夠留下來的Base里面的數據肯定是Derived<J>里面的數據。講到這里應該很清楚了。如果讀者還沒想到這跟反射有什么關系的話,那么請想一下,如果Base除了size以外,還有一個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++有關系的東西。假設ITypeDescriptor是一個足夠代表反射功能的高級接口的話,那么我們要怎么實現它呢?我們自己來按照字符串去調用各種函數什么的去實現它肯定麻煩到死了。但是如果大家還記的我前面的這篇博客文章的話,那么大家肯定想到了,我們可以寫一個程序來替我們讀pdb生成ITypeDescriptor的代碼,還有把具體的對象賦值進Derived<T>::type里面去的一個初始化函數!啊哈哈哈!當然pdb只能是從Visual C++編譯出來的,就算不是,也至少只能是Windows上面的。不過對GacUI來說并無所謂。因為我只要把GacUI在VisualStudio里面編譯生成反射的代碼,這個生成之后的代碼我還是能放到其他地方編譯的。到時候我只要連同這段代碼一并發布就好了。

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

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

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

            當然另一個原因是,我已經熟悉了模板元編程了,所以我的代碼里面免不了有復雜的模板推導,實現這個的確是困難的。  回復  更多評論
              
            # re: C++反射實現方法設想(GacUI) 2012-01-13 18:26 | ooseven
            c++下還沒有優秀的,小型的類wpf gui框架,就等你了!  回復  更多評論
              
            # re: C++反射實現方法設想(GacUI) 2014-07-20 05:54 | qicosmos
            其實我還想到了一種可行的方法,通過tuple把類的元信息返回出去,返回出去之后就可以通過變參來做自己想做的事情了。  回復  更多評論
              
            国产亚洲精品美女久久久| 伊人久久大香线蕉亚洲| 嫩草影院久久99| 亚洲精品国产第一综合99久久| 久久综合亚洲鲁鲁五月天| 精品久久8x国产免费观看| 国产精品xxxx国产喷水亚洲国产精品无码久久一区 | 精品人妻伦九区久久AAA片69 | 午夜欧美精品久久久久久久| 7777久久亚洲中文字幕| 欧美亚洲日本久久精品| 久久777国产线看观看精品| 午夜精品久久影院蜜桃| 久久久久夜夜夜精品国产| 久久午夜免费视频| 国产香蕉97碰碰久久人人| 色狠狠久久AV五月综合| 欧美日韩中文字幕久久久不卡| 97久久天天综合色天天综合色hd| 久久综合久久综合亚洲| 久久se精品一区精品二区国产| 久久99精品国产自在现线小黄鸭| 日韩电影久久久被窝网| 国产精品gz久久久| 久久国产精品久久精品国产| 久久夜色精品国产噜噜麻豆| 久久精品国产亚洲AV蜜臀色欲| 亚洲欧美精品伊人久久| 国产成人精品久久免费动漫| 久久久精品2019免费观看| 色综合久久无码五十路人妻| 久久精品极品盛宴观看| 久久99国产精品久久99小说| 日本国产精品久久| 亚洲色欲久久久久综合网 | 欧美黑人激情性久久| 久久婷婷五月综合成人D啪 | 狠狠色狠狠色综合久久| 中文字幕久久久久人妻| 亚洲欧美伊人久久综合一区二区 | 精品久久久久久无码人妻蜜桃|