• <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>

            馭風萬里無垠

            用Boost.Python + CMake + wxPython構建跨語言GUI程序<三>

            • Class Exposition

            類是OO編程關于封裝的基本單元,圍繞其相關的主要是虛函數、成員變量、成員函數、構造、析構、繼承、多態的問題。

            本示例新建于一個ExposeClass的子項目目錄,并且生成expose_class.so這個模塊庫。

            前邊已經穿插了一些基本的使用方法,下邊是一些更復雜的東西。

            1> 構造函數重載和數據成員、屬性

            c++里邊運行聲明多個構造函數,并且一旦用戶聲明一個,編譯器不再生成默認構造函數;對于數據成員有簡單的public/private/protected三種訪問權限控制,以及很多人采用的getter/setter來模擬的屬性接口。對于構造函數重載,只需要多聲明幾個init函數即可,對于屬性和數據成員,可如下施為:

            ///////////////////////////////////////////////////////////////////////////////
            struct World
            {
                //Constructors
                World(int i){ this->msg = "int parameter";}
                World(std::string msg) {this->msg = msg;} 
            
                //Simple interface
                void set(std::string msg) { this->msg = msg; }
                std::string greet() { return msg; }
                std::string msg;
                //Data variable
                int name;
                int value;
                //Property
                std::string getProp() {return prop;}
                void setProp(const std::string& val) {prop = val;}
            private:
                std::string prop;
            };
            

            上述的類可如下導出:

            BOOST_PYTHON_MODULE(expose_class)
            {
                class_<World>("World", init<std::string>())
                    .def(init<int>())
                    .def("greet", &World::greet)
                    .def("set", &World::set)
                    .def_readonly("name", &World::name)
                    .def_readwrite("value", &World::value)
                    .add_property("roprop", &World::getProp)
                    .add_property("prop", &World::getProp, &World::setProp)
                    ;

            上邊的init模板函數用于制定額外的構造函數。

            read_only指定對應的name成員為只讀,read_write則說明對應的value是可讀寫的數據成員。

            add_property則添加一個對應名字的Python熟悉,第一個參數為get方法的接口,第二個為set方法接口,如果只有一個被提供,那么對應的就是一個只讀屬性。

            調用例子如下:

            >>> import expose_class as cls
            >>> cls.World("str")
            <expose_class.World object at 0x7f3e29529e10>
            >>> cls.World(124)
            <expose_class.World object at 0x7f3e29529d60>
            >>> obj=_
            >>> obj.name="name"
            Traceback (most recent call last):
              File "<stdin>", line 1, in <module>
            AttributeError: can't set attribute
            >>> obj.name
            1
            >>> obj.value="value"
            Traceback (most recent call last):
              File "<stdin>", line 1, in <module>
            Boost.Python.ArgumentError: Python argument types in
                None.None(World, str)
            did not match C++ signature:
                None(World {lvalue}, int)
            >>> obj.value=12
            >>> obj.roprop="name"
            Traceback (most recent call last):
              File "<stdin>", line 1, in <module>
            AttributeError: can't set attribute
            >>> obj.roprop
            ''
            >>> obj.prop = "name"
            >>> obj.name
            1
            >>> obj.value
            12
            >>> 

            上邊例子中,企圖對read_only的變量或者屬性進行賦值的時候均發生異常而報錯。

            2> 抽象類

            所謂的抽象類意指其構造函數不能被外部調用,需要通過factory method來返回一個多態的指針,指向構造的子對象。

            下邊是個簡單的抽象類的例子:

            ///////////////////////////////////////////////////////////////////////////////
            //Abstract class
            struct Abstract
            {
                static std::string msg;
                void set(std::string msg) { this->msg = msg; }
                std::string greet() { return msg; }
            
                static Abstract* CreateInstance()
                {
                    return new Abstract();
                }
            };
            
            std::string Abstract::msg = "default value";

            導出的情況如下:

            class_<Abstract>("Abstract", no_init)
                .def("greet", &Abstract::greet)
                .def("set", &Abstract::set)
                ; 

                 def("CreateAbstract", Abstract::CreateInstance,
                         return_value_policy<manage_new_object>());

            這里的no_init就是指定沒有構造函數可調用。

            >>> import expose_class as test
            >>> test.Abstract()
            Traceback (most recent call last):
              File "<stdin>", line 1, in <module>
            RuntimeError: This class cannot be instantiated from Python
            >>> obj=test.CreateAbstract()
            >>> obj.greet()
            'default value'

            調用的時候,如果調用了這個Abstract的構造,就會拋出異常。對于factory method,由于返回的對象是函數內部構造于堆上的,因此用return_value_policy顯示的指明其生存期。

            3> 繼承和虛函數

            虛函數是c++實現多態機制和OO動態的核心所在,這里主要關注兩種情況,一種是純虛函數(強制之類提供自己的實現),一種是基類提供了默認實現的普通虛函數。

            對于繼承而言,必須通過一個wrapper類來告知boost.python各個類之間的繼承關系。

            純虛函數和一般虛函數的區別僅僅是沒有默認實現,在導出的時候,一般虛函數要多提供一個基類默認實現的函數,而純虛函數需要特別修飾聲明一下。

            參考下邊這兩個類:

            ///////////////////////////////////////////////////////////////////////////////
            //Inheritance
            struct Base 
            {   
                virtual ~Base() {}; 
            
                //Virtual interface
                virtual int fun() = 0;
            
                virtual int func1(int i)
                {
                    cout << "Default implementtion of func1" << endl;
                    return 0;
                }
            };
            
            struct Derived : Base
            {
                virtual int fun()
                {
                    cout << "Derived implementation of fun!" << endl;
                    return 0;
                }
            
                virtual int func1(int i)
                {
                    cout << "Derived implementation of func1!" << endl;
                    return 0;
                }
            };
            
            接下來需要聲明一個wrapper類作為基礎來導出,告知基類信息。這里用了兩個函數,一個是純虛函數fun, 一個是普通虛函數func1.
            對于純虛函數,只需要通過get_override得到具體的函數對象并調用即可(因為基類沒有實現);
            對于純虛函數,則要根據get_override的結果決定是否是基類,然后分別調用對應的函數。
            具體的wrapper代碼如下:
            
            struct BaseWrap : Base, wrapper<Base>
            {
                //pure virtual implementation
                int fun()
                {
                    return this->get_override("fun")();
                }
            
                //pure virtual with default implementation
                int func1(int i)
                {
                    if (override f = this->get_override("func1"))
                    {
                        return f(i);
                    }
                    else
                        return Base::func1(i);
                }
                int default_func1(int i) {return Base::func1(i);}
            };
            導出的代碼:
                class_<BaseWrap, boost::noncopyable>("Base")
                    .def("fun", pure_virtual(&Base::fun))
                    .def("fun1", &Base::func1, &BaseWrap::default_func1)
                    ;
                class_<Derived, bases<Base> >("Derived");

            這里在導出Derived的時候,直接用bases模板參數告知Boost.python它是Base的之類(不是BaseWrap的)。

            4> Factory method

            對于缺乏virtual contructor機制的c++來說,Factory method是一個很常用的生成之類對象的構造方法,如下(為簡單起見,只生成一個之類對象):

            //Free functions on polymophism
            void baseFunc(Base* ptr)
            {
                ptr->fun();
                ptr->func1(1);
            }
            
            void derivedFunc(Derived* ptr)
            {
                ptr->func1(2);
            }
            
            Base* factoryMethod() { return new Derived; }

            這里也導出這個接口:

                class_<Derived, bases<Base> >("Derived");
                def("baseFunc", baseFunc);
                def("derivedFunc", derivedFunc);
                def("factoryMethod", factoryMethod,
                        return_value_policy<manage_new_object>());

            調用的例子:

            >>> base_obj=test.Base()
            >>> dev_obj=test.Derived()
            >>> base_obj.fun()
            Traceback (most recent call last):
              File "<stdin>", line 1, in <module>
            RuntimeError: Pure virtual function called
            >>> dev_obj.fun()
            Derived implementation of fun!
            0
            >>> base_obj.fun1(1)
            Default implementtion of func1
            0
            >>> dev_obj.fun1(1)
            Derived implementation of func1!
            0
            >>> poly_obj=test.factoryMethod()
            >>> test.baseFunc(poly_obj)
            Derived implementation of fun!
            Derived implementation of func1!
            

            posted on 2009-08-10 21:33 skyscribe 閱讀(1101) 評論(0)  編輯 收藏 引用

            <2009年8月>
            2627282930311
            2345678
            9101112131415
            16171819202122
            23242526272829
            303112345

            導航

            統計

            常用鏈接

            留言簿(3)

            隨筆分類

            隨筆檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            午夜欧美精品久久久久久久| 一级做a爰片久久毛片免费陪 | 69SEX久久精品国产麻豆| 99精品久久精品一区二区| 人人狠狠综合久久亚洲婷婷| 久久人人爽人人爽人人片AV麻豆 | 日本精品久久久中文字幕| 无码乱码观看精品久久| 久久99精品久久久久久动态图| 久久se精品一区精品二区国产| 亚洲人成网亚洲欧洲无码久久| 欧美一区二区精品久久| 亚洲欧美成人综合久久久| 国产精品va久久久久久久| 亚洲va中文字幕无码久久不卡| 久久久久久久久久免免费精品 | 亚洲?V乱码久久精品蜜桃| 97久久精品人妻人人搡人人玩| 精品国产乱码久久久久软件| 品成人欧美大片久久国产欧美| 人人狠狠综合久久88成人| 中文字幕无码久久久| 久久精品一区二区影院 | 精品精品国产自在久久高清| 久久精品国产亚洲AV不卡| 欧美一级久久久久久久大| 99久久国产主播综合精品| 国产亚洲色婷婷久久99精品| 无码精品久久久天天影视| 久久久精品国产| 三级三级久久三级久久| 久久亚洲日韩看片无码| 一日本道伊人久久综合影| 亚洲天堂久久久| 亚洲AV日韩精品久久久久久 | 亚洲国产精品成人久久蜜臀 | 久久精品九九亚洲精品| 亚洲精品无码久久久久久| 精品综合久久久久久97| 伊人久久久AV老熟妇色| 久久天天躁狠狠躁夜夜躁2014|