• <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>
            posts - 319, comments - 22, trackbacks - 0, articles - 11
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

                 摘要: 介紹LuaPlus: 好用的Lua For C++擴展(修訂)LuaPlus是Lua的C++增強,也就是說,LuaPlus本身就是在Lua的源碼上進行增強得來的。用它與C++進行合作,是比較好的一個選擇。LuaPlus目前版本為:LuaPlus for Lua 5.01 Distribution Build 1080 (February 28, 2004)。大家可以到http://luaplus....  閱讀全文

            posted @ 2011-08-03 07:42 RTY 閱讀(458) | 評論 (0)編輯 收藏

            Stable release

            The latest stable release of PyInstaller is 1.5.1 (Change Log). See below for download links.

            Features

            • Packaging of Python programs into standard executables, that work on computers without Python installed.
            • Multiplatform: works under Windows (32-bit and 64-bit), Linux (32-bit and 64-bit) and Mac OS X (32-bit only, 64-bit in svn, see MacOsCompatibility).
            • Multiversion: works under any version of Python from 2.2 up to 2.7.
            • Flexible packaging mode:
              • Single directory: build a directory containing an executable plus all the external binary modules (.dll, .pyd, .so) used by the program.
              • Single file: build a single executable file, totally self-contained, which runs without any external dependency.
              • Custom: you can automate PyInstaller to do whatever packaging mode you want through a simple script file in Python.
            • Explicit intelligent support for many 3rd-packages (for hidden imports, external data files, etc.), to make them work with PyInstaller out-of-the-box (see SupportedPackages).
            • Full single-file EGG support: required .egg files are automatically inspected for dependencies and bundled, and all the egg-specific features are supported at runtime as well (entry points, etc.).
            • Partial directory EGG support: required .egg directories are automatically inspected for dependencies and bundled, but egg-specific features will not work at runtime.
            • Automatic support for binary libraries used through ctypes (see CtypesDependencySupport for details).
            • Support for automatic binary packing through the well-known  UPX compressor.
            • Optional console mode (see standard output and standard error at runtime).
            • Windows-specific features:
              • Support for code-signing executables.
              • Full automatic support for CRTs: no need to manually distribute MSVCR*.DLL, redist installers, manifests, or anything else; true one-file applications that work everywhere! (seePython26Win)
              • Selectable executable icon.
              • Fully configurable version resource section and manifests in executable.
              • Support for building COM servers.
            • Mac-specific features:

            License

            PyInstaller is distributed under the GPL license (see the file doc/LICENSE.GPL in the source code), with a special exception which allows to use PyInstaller to build and distribute non-free programs (including commercial ones). In other words, you have no restrictions in using PyInstaller as-is, but any kind of modifications to it will have to comply with the GPL license. See also our FAQ.

            posted @ 2011-08-02 07:28 RTY 閱讀(531) | 評論 (0)編輯 收藏

            在 C++ 中使用 Python script

            想要在c++ 中嵌入script 代碼, 除了自己寫腳本引擎外, lua, python 都可以在c++ 中使用, 另外MonoBind, AngelScript library 都是一些c++ script library, 可以嵌入到c++ 中使用 . 
            今天在c++ 中試著嵌入 python 代碼 (示例代碼在 Python-2.5.2\Demo\embed\ 下)

            #include <Python.h>
            int main(int argc, char *argv[])
            {
              
            // Py_NoSiteFlag = 1;
              
            // Py_SetPythonHome("D:\\usr\\Python"); // PYTHONHOME

              Py_Initialize();
              PyRun_SimpleString(
            "from time import time,ctime\n"
                                 
            "print 'Today is',ctime(time())\n");
              Py_Finalize();
              
            return 0;
            }

            在運行時可能會產生類似 'import site' failed; use -v for traceback 的錯誤, 原因是python 在import module 的時候的路徑問題. 有3種方法可以解決(以前通過設置環境變量 PYTHONPATH 好像在2.5 已經無效了). 
            0. 取消注釋 Py_NoSiteFlag = 1; 
            這個只是取消import site , 當然如果在代碼中要import 啥的話, 還是會出現錯誤的. 
            a. 設置環境變量 PYTHONHOME = D:\usr\Python  
            b. 在調用 Py_Initialize 之前調用函數 
            Py_SetPythonHome("D:\\usr\\Python");  // 參數是python 的安裝目錄 

            2. 其他一些有用的資源 
            Python/C API Reference Manual (API 參考) ,  Extending and Embedding the Python Interpreter (擴展及嵌入Python解釋器, 主要說明了如何擴展Python, 給Python 寫擴展, 其中 5. Embedding Python in Another Application  一章講述了在C++中嵌入/調用Python 代碼 ) 

            使用C/C++擴展Python  對文 Extending and Embedding the Python Interpreter 作了精簡, 很不錯的一篇文章, 但是跳過了一些基礎 . 

            Building Hybrid Systems with Boost.Python 介紹了使用boost.python 方便python 插件開發,python綁定c++程序 是其中文版本. 

            Embedding Python in Multi-Threaded C/C++ Applications 講了c++在多線程環境如何使用Python , 文 C++多線程中調用python api函數 提供了一個多線程的封裝. 

            SCXX - A Simple Python/C++ API
            http://davidf.sjsoft.com/mirrors/mcmillan-inc/scxx.html

            C++擴展和嵌入Python應用 (介紹了一些Python/C API 函數, 以及ext 例子, 一般般) 
            http://hi.baidu.com/yunsweet/blog/item/20b08aeebaa2b1282cf534c7.html


            3. Python 多線程的使用 

            zz http://blog.csdn.net/liguangyi/archive/2007/06/20/1659697.aspx 
            今天看了近一天關于多線程的應用中,如何安全調用python方面的資料,開始的時候看的簡直頭大如斗,被python語言的全局鎖(Global Interpreter Lock)、線程狀態(Thread State )等都有點繞暈了,后來經過各方面文章和幫助文檔的相互參考,發現對于2.4/2.5版本,提供了PyGILState_Ensure, PyGILState_Release,哎,這下可方便大發了。

            一、首先定義一個封裝類,主要是保證PyGILState_Ensure, PyGILState_Release配對使用,而且這個類是可以嵌套使用的。

            #include <python.h>

            class PyThreadStateLock
            {
            public:
                PyThreadStateLock(void)
                {
                    state = PyGILState_Ensure( );
                }

                ~PyThreadStateLock(void)
                {
                     PyGILState_Release( state );
                }
            private:
                PyGILState_STATE state;
            };


            二、在主線程中,這樣處理

                // 初始化
                Py_Initialize();
                // 初始化線程支持
                PyEval_InitThreads();
                // 啟動子線程前執行,為了釋放PyEval_InitThreads獲得的全局鎖,否則子線程可能無法獲取到全局鎖。
                PyEval_ReleaseThread(PyThreadState_Get());
               
                // 其他的處理,如啟動子線程等
                ......
                   
                // 保證子線程調用都結束后
                PyGILState_Ensure();
                Py_Finalize();
                // 之后不能再調用任何python的API

            三、在主線程,或者子線程中,調用python本身函數的都采用如下處理

                {
                    class PyThreadStateLock PyThreadLock;
                    // 調用python的API函數處理
                    ......
                }

            呵呵,看這樣是否非常簡單了。


            另外還有兩個和全局鎖有關的宏,Py_BEGIN_ALLOW_THREADS 和 Py_END_ALLOW_THREADS。這兩個宏是為了在較長時間的C函數調用前,臨時釋放全局鎖,完成后重新獲取全局鎖,以避免阻塞其他python的線程繼續運行。這兩個宏可以這樣調用

                {
                    class PyThreadStateLock PyThreadLock;
                    // 調用python的API函數處理
                    ......

                    Py_BEGIN_ALLOW_THREADS
                    // 調用需要長時間的C函數
                    ......
                    Py_END_ALLOW_THREADS

                    // 調用python的API函數處理
                    ......
                }

            4. 可能的錯誤及解決 
            a. 在vs 200x 下 debug 模式出現鏈接問題 
            extmodule.obj : error LNK2019: unresolved external symbol __imp___Py_Dealloc referenced in function _PySwigObject_format
            extmodule.obj : error LNK2019: unresolved external symbol __imp___Py_NegativeRefcount referenced in function _PySwigObject_format
            extmodule.obj : error LNK2001: unresolved external symbol __imp___Py_RefTotal
            extmodule.obj : error LNK2019: unresolved external symbol __imp___PyObject_DebugFree referenced in function _PySwigObject_dealloc
            extmodule.obj : error LNK2019: unresolved external symbol __imp___PyObject_DebugMalloc referenced in function _PySwigObject_New
            extmodule.obj : error LNK2019: unresolved external symbol __imp__Py_InitModule4TraceRefs referenced in function _init_extmodule

            主要是因為 Py_DEBUG/Py_TRACE_REFS 引起, 修改 Python\include 下的 pyconfig.h, object.h 兩個文件就行了 ... 詳見 http://www.nabble.com/link-error-in-debug-mode-td3126668.html 

            posted on 2008-08-14 17:55 泡泡牛 閱讀(4472) 評論(3)  編輯 收藏 引用 所屬分類: Python

            評論

            # re: 在 C++ 中使用 Python script  2008-08-15 20:34 泡泡牛 

            誰知道有什么其他的可以在c++ 里面調用的script 引擎嗎?
              回復  更多評論    

            # re: 在 C++ 中使用 Python script  2008-09-24 20:10 sheena 

            主要是因為 Py_DEBUG/Py_TRACE_REFS 引起, 修改 Python\include 下的 pyconfig.h, object.h 兩個文件就行了 ... 詳見 http://www.nabble.com/link-error-in-debug-mode-td3126668.html 
            這個解釋我還是沒有看明白,?您能再解釋下嗎
              回復  更多評論    

            # re: 在 C++ 中使用 Python script  2008-09-24 22:17 泡泡牛 

            1. 修改 pyconfig.h 

            修改 

            #ifdef _DEBUG 
            # define Py_DEBUG 
            #endif 

            為 

            #ifdef _DEBUG 
            //# define Py_DEBUG 
            #endif 

            修改 

            # ifdef _DEBUG 
            # pragma comment(lib,"python24_d.lib") 
            # else 
            # pragma comment(lib,"python24.lib") 
            # endif /* _DEBUG */ 

            為 

            # ifdef _DEBUG 
            # pragma comment(lib,"python24.lib") 
            # else 
            # pragma comment(lib,"python24.lib") 
            # endif /* _DEBUG */ 


            2. object.h 
            修改 
            #if defined(Py_DEBUG) && !defined(Py_TRACE_REFS) 
            #define Py_TRACE_REFS 
            #endif 

            為 

            #if defined(Py_DEBUG) && !defined(Py_TRACE_REFS) 
            // #define Py_TRACE_REFS 
            #endif

            posted @ 2011-07-28 07:24 RTY 閱讀(806) | 評論 (0)編輯 收藏

            Bitdefender 全方位安全殺毒軟件激活碼(序列號)/Bitdefender Internet Security正版激活碼
             說明:以下激活碼(序列號)適用Bitdefender Internet Security 2011
            BitDefender Internet Security 2011正版激活碼一年期,可激活最新版本2011
            激活碼 67PIDQD

            BitDefender Internet Security 2011激活碼一枚【LA0G】(365天)
            激活碼 NGELA0G


            BitDefender Internet Security 2011激活碼一枚【5X3Q】(180天)
            激活碼 SQA5X3Q


            BitDefender Internet Security 2011激活碼一枚【14A2】(283天)
            14A20BF746E7C46DC941


            BitDefender Internet Security 2011最新激活碼(180天)

            激活碼
            5LLHJ7I         356天
            AIFRUVN         173天
            N7T5033         173天
            5UZXTCE         175天
            XLWWGV0         1051天


            BitDefender Internet Security 2011激活碼【NDS0】(152天)
            激活碼 QVUNDS0


            BitDefender Internet Security 2011可疊加180天激活碼兩枚
            激活碼: LTHGXPX
            激活碼: LFWHQ4Y


            BitDefender Internet Security 2011最新激活碼(180天)兩枚
            激活碼: 4J24PJJ
            激活碼: YVKAS47

            posted @ 2011-07-26 22:24 RTY 閱讀(774) | 評論 (0)編輯 收藏

            看到const 關鍵字,C++程序員首先想到的可能是const 常量。這可不是良好的條件反射。如果只知道用const 定義常量,那么相當于把火藥僅用于制作鞭炮。const 更大的魅力是它可以修飾函數的參數、返回值,甚至函數的定義體。

            const 是constant 的縮寫,“恒定不變”的意思。被const 修飾的東西都受到強制保護,可以預防意外的變動,能提高程序的健壯性。所以很多C++程序設計書籍建議:“Use const whenever you need”。

            1.用const 修飾函數的參數

            如果參數作輸出用,不論它是什么數據類型,也不論它采用“指針傳遞”還是“引用傳遞”,都不能加const 修飾,否則該參數將失去輸出功能。const 只能修飾輸入參數:

            如果輸入參數采用“指針傳遞”,那么加const 修飾可以防止意外地改動該指針,起到保護作用。

            例如StringCopy 函數:

            void StringCopy(char *strDestination, const char *strSource);

            其中strSource 是輸入參數,strDestination 是輸出參數。給strSource 加上const修飾后,如果函數體內的語句試圖改動strSource 的內容,編譯器將指出錯誤。

            如果輸入參數采用“值傳遞”,由于函數將自動產生臨時變量用于復制該參數,該輸入參數本來就無需保護,所以不要加const 修飾。

            例如不要將函數void Func1(int x) 寫成void Func1(const int x)。同理不要將函數void Func2(A a) 寫成void Func2(const A a)。其中A 為用戶自定義的數據類型。

            對于非內部數據類型的參數而言,象void Func(A a) 這樣聲明的函數注定效率比較底。因為函數體內將產生A 類型的臨時對象用于復制參數a,而臨時對象的構造、復制、析構過程都將消耗時間。

            為了提高效率,可以將函數聲明改為void Func(A &a),因為“引用傳遞”僅借用一下參數的別名而已,不需要產生臨時對象。但是函數void Func(A &a) 存在一個缺點:

            “引用傳遞”有可能改變參數a,這是我們不期望的。解決這個問題很容易,加const修飾即可,因此函數最終成為void Func(const A &a)。

            以此類推,是否應將void Func(int x) 改寫為void Func(const int &x),以便提高效率?完全沒有必要,因為內部數據類型的參數不存在構造、析構的過程,而復制也非常快,“值傳遞”和“引用傳遞”的效率幾乎相當。

            問題是如此的纏綿,我只好將“const &”修飾輸入參數的用法總結一下。

             

            對于非內部數據類型的輸入參數,應該將“值傳遞”的方式改為“const 引用傳遞”,目的是提高效率。例如將void Func(A a) 改為void Func(const A &a)。

             

            對于內部數據類型的輸入參數,不要將“值傳遞”的方式改為“const 引用傳遞”。否則既達不到提高效率的目的,又降低了函數的可理解性。例如void Func(int x) 不應該改為void Func(const int &x)。

            2 用const 修飾函數的返回值
            如果給以“指針傳遞”方式的函數返回值加const 修飾,那么函數返回值(即指針)的內容不能被修改,該返回值只能被賦給加const 修飾的同類型指針。例如函數
            const char * GetString(void);
            如下語句將出現編譯錯誤:
            char *str = GetString();
            正確的用法是
            const char *str = GetString();
            如果函數返回值采用“值傳遞方式”,由于函數會把返回值復制到外部臨時的存儲單元中,加const 修飾沒有任何價值。
            例如不要把函數int GetInt(void) 寫成const int GetInt(void)。
            同理不要把函數A GetA(void) 寫成const A GetA(void),其中A 為用戶自定義的數據類型。
            如果返回值不是內部數據類型,將函數A GetA(void) 改寫為const A & GetA(void)的確能提高效率。但此時千萬千萬要小心,一定要搞清楚函數究竟是想返回一個對象的“拷貝”還是僅返回“別名”就可以了,否則程序會出錯。
            函數返回值采用“引用傳遞”的場合并不多,這種方式一般只出現在類的賦值函數中,目的是為了實現鏈式表達。

            例如:
            class A
            {
            A & operate = (const A &other); // 賦值函數
            };
            A a, b, c; // a, b, c 為A 的對象

            a = b = c; // 正常的鏈式賦值
            (a = b) = c; // 不正常的鏈式賦值,但合法
            如果將賦值函數的返回值加const 修飾,那么該返回值的內容不允許被改動。上例中,語句 a = b = c 仍然正確,但是語句 (a = b) = c 則是非法的。
            3 const 成員函數
            任何不會修改數據成員的函數都應該聲明為const 類型。如果在編寫const 成員函數時,不慎修改了數據成員,或者調用了其它非const 成員函數,編譯器將指出錯誤,這無疑會提高程序的健壯性。以下程序中,類stack 的成員函數GetCount 僅用于計數,從邏輯上講GetCount 應當為const 函數。編譯器將指出GetCount 函數中的錯誤。
            class Stack
            {
            public:
            void Push(int elem);
            int Pop(void);
            int GetCount(void) const; // const 成員函數
            private:
            int m_num;
            int m_data[100];
            };
            int Stack::GetCount(void) const
            {
            ++ m_num; // 編譯錯誤,企圖修改數據成員m_num
            Pop(); // 編譯錯誤,企圖調用非const 函數
            return m_num;
            }
            const 成員函數的聲明看起來怪怪的:const 關鍵字只能放在函數聲明的尾部,大概是因為其它地方都已經被占用了。
            關于Const函數的幾點規則:

            a. const對象只能訪問const成員函數,而非const對象可以訪問任意的成員函數,包括const成員函數.
            b. const對象的成員是不可修改的,然而const對象通過指針維護的對象卻是可以修改的.
            c. const成員函數不可以修改對象的數據,不管對象是否具有const性質.它在編譯時,以是否修改成員數據為依據,進行檢查.
            e. 然而加上mutable修飾符的數據成員,對于任何情況下通過任何手段都可修改,自然此時的const成員函數是可以修改它的

            posted @ 2011-07-26 07:14 RTY 閱讀(262) | 評論 (0)編輯 收藏

            const類型定義:指明變量或對象的值是不能被更新,引入目的是為了取代預編譯指令 

            **************常量必須被初始化*************************

            cons的作用
               (1)可以定義const常量         例如:
                         const int Max=100;
                         int Array[Max];        
               (2)便于進行類型檢查            例如:
                         void f(const int i) { .........}
                    編譯器就會知道i是一個常量,不允許修改;
               (3)可以保護被修飾的東西,防止意外的修改,增強程序的健壯性。
                    還是上面的例子,如果在函數體內修改了i,編譯器就會報錯;
                    例如: 
                         void f(const int i) { i=10;//error! }
                (5) 為函數重載提供了一個參考。
                     class A
                     {
                       ......
                       void f(int i)       {......} file://一個函數
                       void f(int i) const {......} file://上一個函數的重載
                        ......
                      };
                 (6) 可以節省空間,避免不必要的內存分配。
                     例如:
                          #define PI 3.14159         file://常量宏
                          const doulbe  Pi=3.14159;  file://此時并未將Pi放入ROM中
                          ......
                          double i=Pi;               file://此時為Pi分配內存,以后不再分配!
                          double I=PI;               file://編譯期間進行宏替換,分配內存
                          double j=Pi;               file://沒有內存分配
                          double J=PI;               file://再進行宏替換,又一次分配內存!
                     const定義常量從匯編的角度來看,只是給出了對應的內存地址,而不是象#define一樣給出的是立即數,所以,const定義的常量在程序運行過程中只有一份拷貝,而#define定義的常量在內存中有若干個拷貝。
                 (7) 提高了效率。
                       編譯器通常不為普通const常量分配存儲空間,而是將它們保存在符號表中,這使得它成為一個編譯期間的常量,沒有了存儲與讀內存的操作,使得它的效率也很高。

            使用const
               (1)修飾一般常量,常數組,常對象
               修飾符const可以用在類型說明符前,也可以用在類型說明符后。      例如:   
                       int const x=2;  或  const int x=2;

                   int const a[5]={1, 2, 3, 4, 5};    或  const int a[5]={1, 2, 3, 4, 5};

                       class A;      const A a;  或     A const a;
                 
               (2)修飾指針
                    const int *A;   或  int const *A; //const修飾指向的對象,A可變,A指向的對象不可變
                    int *const A;              //const修飾指針A,     A不可變,A指向的對象可變 
                    const int *const A;      //指針A和A指向的對象都不可變
               (3)修飾引用
                    const double & v;      該引用所引用的對象不能被更新
             (4)修飾函數的返回值:
                    const修飾符也可以修飾函數的返回值,是返回值不可被改變,格式如下:
                        const int Fun1(); 
                        const MyClass Fun2();
               (5)修飾類的成員函數:
                    const修飾符也可以修飾類的成員函數,格式如下:
                        class ClassName 
                 {
                         public:
                              int Fun() const;
                                .....
                         };
                    這樣,在調用函數Fun時就不能修改類里面的數據 
                (6)在另一連接文件中引用const常量
                     extern const int i;     //正確的引用
                     extern const int j=10;  //錯誤!常量不可以被再次賦值
               


            *******************放在類內部的常量有什么限制?
              
                    class A
                    {
                     private:
                       const int c3 = 7;               // err
                       static int c4 = 7;               // err
                       static const float c5 = 7;  // err
                      ......
              };
             初始化類內部的常量
                    1 初始化列表:
                     class A
                     {
                      public:
                            A(int i=0):test(i) {}
                      private:
                            const int i;
                      };
                     2 外部初始化,例如:
                     class A
                     {
                      public:
                            A() {}
                      private:
                            static const int i;  
                      };
                      const int A::i=3; 

            posted @ 2011-07-26 07:13 RTY 閱讀(221) | 評論 (0)編輯 收藏

            1.虛函數
            1.1虛函數的作用
            虛函數的作用是允許在派生類中重新定義與基類同名的函數,并且可以通過基類指針或引用來訪問基類和派生類中的同名函數。
            class Time{
              public:
                Time(int=0,int=0,int=0);
                void show();
              protected:
                int hour;
                int min;
                int sec;
            };
             
            class LocalTime:public Time{
              public:
                LocalTime(int=0,int=0,int=0,string="+8");
                void show();
              protected:
                string zone;
            };
             
            Time::Time(int h,int m,int s):hour(h),min(m),sec(s){}
             
            void Time::show(){
              cout<<hour<<":"<<min<<":"<<sec<<endl;
            }
             
            LocalTime::LocalTime(int h,int m,int s,string z):Time(h,m,s),zone(z){}
             
            void LocalTime::show(){
              cout<<hour<<":"<<min<<":"<<sec<<"@"<<zone<<endl;    
            }
             
            int main(){
              Time t;
              LocalTime lt;
              Time *pt=&t;
              pt->show();
              pt=&lt;
              pt->show();
              system("PAUSE");
              return EXIT_SUCCESS;
            }
            結果:
            0:0:0
            0:0:0
            這里通過指針找到派生類,但無法調用派生類show()。如果使用虛函數。
            將基類Time中的show()函數聲明為虛函數, 其余不變。
            class Time{
              public:
                Time(int=0,int=0,int=0);
                virtual void show();
            };
            結果:
            0:0:0
            0:0:0@+8
            本來,基類指針是指向基類對象的,如果用它指向派生類對象,則進行指針類型轉換,將派生類對象的指針先轉換為基類指針,所以基類指針指向的是派生類對象中的基類部分。在程序修改前,是無法通過基類指針去調用派生類對象中的成員函數的。
            虛函數突破這一限制,在派生類的基類部分中,派生類的虛函數取代了基類原來的虛函數,因此在使用基類指針指向派生類對象后,調用虛函數時就調用了派生類的虛函數。
             
            1.2虛函數的使用方法
            【1】在基類用virtual聲明成員函數為虛函數。這樣就可以在派生類中重新定義此函數,為它賦予新的功能,并能方便地被調用。
             
            【2】在派生類中重新定義此函數,要求函數名、函數(返回)類型、函數參數個數和類型與基函數的虛函數相同。如果在派生類中沒有對基類的虛函數重定義,則派生類簡單地繼承直接基類的虛函數。
            有一種情況例外,在這種情況下派生類與基類的成員函數返回類型不同,但仍起到虛函數的作用。即基類虛函數返回一個基類指針或基類引用,而子類的虛函數返回一個子類的指針或子類的引用。
            class Base{
              public:
                virtual Base *fun(){
                  cout<<"Base's fun()."<<endl;
                  return this;
                }
            };
             
            class Derived:public Base{
              public:
                virtual Derived *fun(){
                  cout<<"Derived's fun()."<<endl;
                  return this;
                }
            };
             
            void test(Base &x){
              Base *b;
              b=x.fun();
            }
             
            int main(){
              Base b; 
              Derived d;
              test(b);
              test(d);   
              system("PAUSE");
              return EXIT_SUCCESS;
            }
            結果:
            Base's fun().
            Derived's fun().
             
            【3】C++規定,當一個成員函數被聲明為虛函數后,其派生類中的同名函數(符合2中定義的函數)都自動成為虛函數。
             
            【4】定義一個指向基類對象的指針變量,并使其指向同一類族中的某個對象。通過該指針變量調用此函數,此時調用的就是指針變量指向的對象的同名函數。
             
            1.3聲明虛函數的限制
            【1】只能用virtual聲明類的成員函數,使它成為虛函數,而不能將類外的普通函數聲明為虛函數。
             
            【2】一個成員函數被聲明為虛函數后,在同一類族中的類就不能再定義一個非virtual的但與該虛函數具有相同參數(個數與類型)和函數返回值類型的同名函數。
             
            【3】靜態成員函數不能是虛函數,因為靜態成員函數不受限于某個對象。
             
            【4】inline函數不能是虛函數,因為inline函數是不能在運行中動態確定其位置的。即使虛函數在類的內部定義,編譯時,仍將其視為非inline的。
             
            【5】使用虛函數,系統要有一定的空間開銷。當一個類帶有虛函數時,編譯器會為該類構造一個虛函數表(virtual function tanle,vtable),它是一個指針數組,存放每個虛函數的入口地址。
            2.虛析構函數
            class Time{
              public:
                Time(int=0,int=0,int=0);
                ~Time(){
                  cout<<"Time destructor"<<endl;
                }       
              protected:
                int hour;
                int min;
                int sec;
            };           
             
            class LocalTime:public Time{
              public:
                LocalTime(int=0,int=0,int=0,string="+8");
                ~LocalTime(){
                  cout<<"LocalTime destructor"<<endl;
                }
              protected:
                string zone;
            };                 
             
            Time::Time(int h,int m,int s):hour(h),min(m),sec(s){}
             
            LocalTime::LocalTime(int h,int m,int s,string z):Time(h,m,s),zone(z){}
             
            int main(){
              Time *p=new LocalTime;//指向派生類
              delete p;  
              system("PAUSE");
              return EXIT_SUCCESS;
            }
            結果:
            Time destructor
            從結果可以看出,執行的還是基類的析構函數,而程序的本意是希望執行派生類的析構函數。此時將基類的析構函數聲明為虛析構函數,
            virtual ~Time(){
              cout<<"Time destructor"<<endl;
            }
            結果:
            LocalTime destructor
            Time destructor
            如果將基類的析構函數聲明為虛函數,由該基類所派生的所有派生類的析構函數也自動成為虛函數。
            把基類的析構函數聲明為虛函數的好處是,如果程序中delete一個對象,而delete運算符的操作對象是指向派生類對象的基類指針,則系統會調用相應類的析構函數。
            構造函數不能聲明為虛函數。
            3.純虛函數
            virtual void show()=0;//純虛函數
            這里將show()聲明為純虛函數(pure virtual function)。純虛函數是在聲明虛函數時被“初始化”為0的虛函數。
            聲明純虛函數的一般形式為,
            virtual 函數類型 函數名(參數列表)=0;
            純虛函數沒有函數體;最后的“=0”并不代表函數返回值為0,它只起形式上的作用,告訴編譯器“這是純虛函數”;這個一個聲明語句,最后有分號。
            聲明純虛函數是告訴編譯器,“在這里聲明了一個虛函數,留待派生類中定義”。在派生類中對此函數提供了定義后,它才能具備函數的功能,可以被調用。
            純虛函數的作用是在基類中為其派生類保留了一個函數的名字,以便派生類根據需要對它進行定義。
            如果在一個類中聲明了純虛函數,而在其派生類中沒有對該函數定義,則該函數在派生類中仍為純虛函數。
            4.抽象類
            將不用來定義對象而只作為一種基本類型用作繼承的類,稱為抽象類(abstract class),由于它常用作基類,通常稱為抽象基類。凡是包含純虛函數的類都是抽象類。
            如果在派生類中沒有對所有的純虛函數進行定義,則此派生類仍然是抽象類,不能用來定義對象。
            可以定義指向抽象類數據的指針變量。當派生類成為具體類后,就可以用這個指針指向派生類對象,然后通過該指針調用虛函數。

            posted @ 2011-07-26 06:59 RTY 閱讀(478) | 評論 (0)編輯 收藏

            1.  Qt 全局宏定義

            Qt版本號:

             QT_VERSION :  (major << 16) + (minor << 8) + patch

            檢測版本號:

            QT_VERSION_CHECK(major, minor, patch)((major<<16)|(minor<<8)|(patch))

            當使用命名空間時的一些宏定義:

            namespace QT_NAMESPACE {} //命名空間定義

            # define QT_PREPEND_NAMESPACE(name) ::QT_NAMESPACE::name

            # define QT_USE_NAMESPACE using namespace ::QT_NAMESPACE;

            # define QT_BEGIN_NAMESPACE namespace QT_NAMESPACE {

            # define QT_END_NAMESPACE }

            # define QT_BEGIN_INCLUDE_NAMESPACE }

            # define QT_END_INCLUDE_NAMESPACE namespace QT_NAMESPACE {

            # define QT_BEGIN_MOC_NAMESPACE QT_USE_NAMESPACE

            # define QT_END_MOC_NAMESPACE

            # define QT_FORWARD_DECLARE_CLASS(name) /

                QT_BEGIN_NAMESPACE class name; QT_END_NAMESPACE /

                using QT_PREPEND_NAMESPACE(name);

             

            # define QT_FORWARD_DECLARE_STRUCT(name) /

                QT_BEGIN_NAMESPACE struct name; QT_END_NAMESPACE /

                using QT_PREPEND_NAMESPACE(name);

            Q_GLOBAL_STATIC(type, name)用于定義一個全局的靜態變量(線程安全的).用它來初始化一個對象指針(函數指針).

            Q_GLOBAL_STATIC_WITH_ARGS(type, name, arguments):同上,可帶參數.

             

            Q_UNUSED():通常用于某個函數的參數,表明該參數未在方法體中使用.

            常用數據類型:

            qint8, quint8, qint16, quint16, qint32, quint32, qint64, quint64, qlonglong(=int64), qulonglong(=uint64)

            quintptr, qptrdiff, 作為指針是一樣大的.如:

                  sizeof(void *) == sizeof(quintptr)

                  && sizeof(void *) == sizeof(qptrdiff)

            Qt有用的類型定義:uchar, ushort, uint, ulong

            實用內聯函數:qAbs(), qRound(), qRound64(), qMin(), qMax(), qBound();

            try-catch宏:

            #ifdef QT_NO_EXCEPTIONS

            #  define QT_TRY if (true)

            #  define QT_CATCH(A) else

            #  define QT_THROW(A) qt_noop()

            #  define QT_RETHROW qt_noop()

            #else

            #  define QT_TRY try

            #  define QT_CATCH(A) catch (A)

            #  define QT_THROW(A) throw A

            #  define QT_RETHROW throw

            #endif

            每個QT_TRY對應一個QT_CATCH,不要在catch語句塊中使用異常實例.

             

            調試相關函數:

            qDebug(), qWarnig(), qCritical(), Q_ASSERT()

             

            其他一些函數:

            該宏用于定義某個類,禁止拷貝

            #define Q_DISABLE_COPY(Class) /

                Class(const Class &); /

                Class &operator=(const Class &);

            qgetenv(), qputenv(), qIntCast(double 或float). qsrand(uint seed), qrand()

            2. Qt的內存管理函數

            void *qMalloc(size_t size);

            void qFree(void *ptr);

            void *qRealloc(void *ptr, size_t size);

            void *qMallocAligned(size_t size, size_t alignment)

            void *qReallocAligned(void *oldptr, size_t newsize, size_t oldsize, size_t alignment)

            void qFreeAligned(void *ptr)

            void *qMemCopy(void *dest, const void *src, size_t n);

            void *qMemSet(void *dest, int c, size_t n);

            注: 數組下標為-1的地址對于數組來說是越界訪問了,但是這個地址是有意義的.這個地址就是所申請的數組存儲空間的首地址的向前偏移一個單位(也就是偏移一個當前數組類型所對應的字節數)所對應的地址。這個地址由于沒有跟著數組空間一起初始化,所以其中的數據是不確定的.如果是正在被系統或者其他應用程序使用中的地址空間,那么可以被訪問,其中的數據的意義取決于被系統或者其他應用程序所寫入的數據,但是訪問后,有可能會引起系統或者其他應用程序異常。如果是沒有被使用的地址,那么就是一個野地址,那么其中的數據是隨機的,無意義的

             

            3. 環境變量設置函數

            qputenv():與putenv()基本類似,由于VC2005后廢除了putenv()函數,所有定義了此函數,在VC環境中調用替代的函數,其他平臺調用標準C庫函數putenv().

            qgetenv():獲取某個環境變量的值.

             

            4.自定義輸出函數

            QtMsgHandler qInstallMsgHandler(QtMsgHandler h)

            其中:typedef void (*QtMsgHandler)(QtMsgType, const char *);

            利用該函數可定制自己的調試信息輸出.

             

            5. 斷言

            Q_ASSERT(bool test):當斷言失敗時,打印出警告信息,包含了源碼文件名和行號.

            void Q_ASSERT_X(bool test, const char *where, const char *what)

             

            void Q_CHECK_PTR(void *pointer):檢測非法指針,如果指針為0,打印警告信息.

             

            6.系統信息類QsysInfo

            posted @ 2011-07-26 06:53 RTY 閱讀(4275) | 評論 (0)編輯 收藏

                 摘要: 比起源碼級別的模塊化,二進制級別的模塊劃分使得各模塊更加獨立,各模塊可以分別編譯和鏈接,模塊的升級不會引起其它模塊和主程序的重新編譯,這點對于大系統的構建來說更加實用。AD:繼續 Qt編寫模塊化插件式應用程序 (上篇) 的內容繼續介紹,本節介紹的是Qt編寫模塊化插件式應用程序 (下篇),我們先來看內容。2. 編寫Animal插件——BilDog和BilP...  閱讀全文

            posted @ 2011-07-26 06:42 RTY 閱讀(602) | 評論 (0)編輯 收藏

                 摘要: 比起源碼級別的模塊化,二進制級別的模塊劃分使得各模塊更加獨立,各模塊可以分別編譯和鏈接,模塊的升級不會引起其它模塊和主程序的重新編譯,這點對于大系統的構建來說更加實用。AD:動態鏈接庫技術使軟件工程師們獸血沸騰,它使得應用系統(程序)可以以二進制模塊的形式靈活地組建起來。比起源碼級別的模塊化,二進制級別的模塊劃分使得各模塊更加獨立,各模塊可以分別編譯和鏈接,模塊的升級不會引起其它模塊和主程序的重新...  閱讀全文

            posted @ 2011-07-26 06:40 RTY 閱讀(538) | 評論 (0)編輯 收藏

            僅列出標題
            共31頁: First 11 12 13 14 15 16 17 18 19 Last 
            97精品久久天干天天天按摩 | 香蕉久久永久视频| 精品国产福利久久久| 国产亚洲精午夜久久久久久| 思思久久99热只有频精品66| 久久精品国产亚洲AV无码麻豆 | 亚洲国产成人精品91久久久| 久久亚洲AV成人无码| 久久人爽人人爽人人片AV| 久久精品无码专区免费| 国产激情久久久久久熟女老人| 久久精品国产一区| 国内精品久久国产| 久久99国产精品久久久| 伊人久久精品无码二区麻豆| 久久成人国产精品一区二区| 久久精品无码一区二区无码| 亚洲国产成人久久一区WWW| 久久成人国产精品二三区| 99精品久久久久久久婷婷| 久久久网中文字幕| 久久国产香蕉一区精品| 久久被窝电影亚洲爽爽爽| 久久久老熟女一区二区三区| 久久成人小视频| 最新久久免费视频| 久久久久久久国产免费看| 久久99精品国产一区二区三区| 久久精品国产91久久麻豆自制 | 久久精品国产99国产精品导航| 国产 亚洲 欧美 另类 久久| 99久久夜色精品国产网站| 思思久久好好热精品国产| 亚洲?V乱码久久精品蜜桃| 日韩十八禁一区二区久久| 国产精品熟女福利久久AV| 丰满少妇人妻久久久久久4| 伊人久久综在合线亚洲2019| 国产ww久久久久久久久久| 久久99国产精品久久99| 97久久综合精品久久久综合|