重載TCLCL中的類

來源:互聯網
上載者:User
1. 問題的由來在使用BlueHoc的過程中,發現它直接修改了ns2的一些核心檔案,那麼是否有一種方式可以不必修改NS2核心檔案而達到同樣的目的呢?2. 思路Ns2使用TCL/CL來將OTCL代碼與C++代碼結合起來,所有的模擬過程都是通過OTCL代碼調用的。那麼是否可以重載OTCL中相同名稱的類,在它們建立時將其指向自己的C++類呢?3. 測試代碼為了測試使用同名的OTCL類是否可以重載的問題,寫了以下的測試代碼:#include <math.h>#include "tclcl.h"extern "C" {#include <otcl.h>} // 定義一個準備讓TCL指令碼調用的類,此類必須從TclObject繼承class CTestObject : public TclObject{private:     int m_nCount;  public:     CTestObject()     {         m_nCount = 0;          // bind之後就可以在TCL指令碼中訪問這個類的成員變數了,         // 對於沒有使用bind的變數是無法通過指令碼訪問的。         // 在此只展示一個簡單的整數類型,如果是複雜資料則需要從TracedVar繼承一個子類進行控制         this->bind("Count", &m_nCount);      }      virtual int init(int argc, const char*const* argv)      {         // 在指令碼中進行執行個體化時將調用此函數         printf("CTestObject::init called/n");         m_nCount = 100;         return (TCL_OK);     }     virtual int command(int argc, const char*const* argv)     {         // 當指令碼中進行對象的函數調用時將使用此函數         printf("CTestObject::command called/n");         if(argc >= 2 && strcmp(argv[1], "GetCount") == 0)         {              char result[20];              sprintf(result, "%d", m_nCount);              Tcl::instance().result(result);              return TCL_OK;         }         else               return TclObject::command(argc, argv);     } }; class CSubTestObject : public CTestObject{private:     int m_nSubCount; public:     CSubTestObject()     {         m_nSubCount = 0;         this->bind("SubCount", &m_nSubCount);     }     virtual int init(int argc, const char*const* argv)      {         // 在指令碼中進行執行個體化時將調用此函數         CTestObject::init(argc, argv);         printf("CSubTestObject::init called/n");         m_nSubCount = 200;         return (TCL_OK);     }     virtual int command(int argc, const char*const* argv)     {         // 當指令碼中進行對象的函數調用時將使用此函數         printf("CSubTestObject::command called/n");         if(argc >= 2 && strcmp(argv[1], "GetSubCount") == 0)         {              char result[20];              sprintf(result, "%d", m_nSubCount);              Tcl::instance().result(result);              return TCL_OK;         }         else               return CTestObject::command(argc, argv);     }}; // 定義一個TCL指令碼中可以使用的類資訊class CTestClass : public TclClass{public:     CTestClass()         : TclClass("CTestClass")     {     }      virtual TclObject* create(int argc, const char* const* argv)     {         // 建立對象時將調用此函數,如果CTestObject的建構函式需要參數也可以從這裡取得         printf("CTestClass::create called/n");         return new CTestObject;     }}; // 不可使用這種變數的方式,否則無法重載//static CTestClass _cls;  // 定義一個TCL指令碼中可以使用的類資訊class CSubTestClass : public TclClass{public:     CSubTestClass()         : TclClass("CTestClass")         // 使用與CTestClass相同的類名稱,看看發生的結果     {     }      virtual TclObject* create(int argc, const char* const* argv)     {         // 建立對象時將調用此函數,如果CTestObject的建構函式需要參數也可以從這裡取得          printf("CSubTestClass::create called/n");         return new CSubTestObject;     }}; // 不可使用這種變數的方式,否則無法重載//static CSubTestClass _sub_cls; // 應先初始化Tcl::init之後再註冊類型資訊,否則無法重載void ClassInit(){     new CTestClass;     new CSubTestClass;}4. 測試中出現的問題在此測試過程中,剛開始使用的是靜態全域變數進行類的註冊,但是發現此種情況下無法重載。跟蹤代碼時發現,在調用TclClass類建構函式時,如果Tcl::instance()未初始化,則建構函式僅僅是將我們的類放在一個單鏈表中,而不會立即進行OTCL類和C++類的綁定。注意此鏈表中後插入的資料是放在表頭的,而初始化完成後進行C++類和OTCL類綁定的時候則是從表頭向表尾按順序進行的,因此就造成了這個問題。根據分析,解決問題的方式也有兩種。第一種仍然使用靜態全域變數的方式,但是要更改父類和子類初始化的先後順序,先定義子類的靜態全域變數,再定義父類的靜態全域變數。第二種不使用全域靜態變數,而是在Tcl::init()調用完成後再進行類的初始化,如上述代碼中的ClassInit(),此時應先初始化父類,再初始化子類。經過上述調整,即可得到正確的結果。  

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.