線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:1344
推到 Plurk!
推到 Facebook!

关于虚函数和接口

尚未結案
ilikeff8
一般會員


發表:12
回覆:16
積分:5
註冊:2002-12-28

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-06-10 15:59:49 IP:218.0.xxx.xxx 未訂閱
我一作业用bcb class IOp // Father Class Uses Sub Class's function and Sub Class fill the function info. { public: virtual void ReadRecord(void){}; virtual void WriteRecord(void){}; virtual SFIELD& FieldByIndex(int){ return NULLFIELD; }; virtual int GetFieldTotalNumber(void){ return 0; }; }; //--------------------------------------------------------------------------- class TRecordActive:public IOp { private: AnsiString FConfigFileName,FSection,FDataFileIdent,DataFile,SearchFieldName, FSearchValue,FSearchValue2,FStringGridName,FSearchComboBoxName; TStringList *RecordNO; void FillRecord(bool); void AddColumn(SFIELD); void FillToStringGrid(void); void GetRecordFromComponents(void); void GetFromStringGrid(int); void PutRecordToComponents(void); void FillSearchComboBoxByFields(void); bool CheckBySearch(SFIELD,AnsiString); bool CheckBySearch(SFIELD,AnsiString,AnsiString); void SetSearchFieldName(AnsiString Value); protected: TForm *FForm; int FHandle; TStringGrid *FStringGrid; void InitStringGrid(void); public: ::TRecordActive(void) { FConfigFileName=""; DataFile=""; FHandle=-1; SearchFieldName=""; FStringGridName=""; FSearchComboBoxName=""; RecordNO=new TStringList(); } ~TRecordActive(void) { delete RecordNO; } __property TForm *Form={read=FForm,write=FForm}; __property AnsiString ConfigFileName={read=FConfigFileName,write=FConfigFileName}; __property AnsiString Section={read=FSection,write=FSection}; __property AnsiString DataFileIdent={read=FDataFileIdent,write=FDataFileIdent}; __property AnsiString StringGridName={read=FStringGridName,write=FStringGridName}; __property AnsiString SearchComboBoxName={read=FSearchComboBoxName,write=FSearchComboBoxName}; bool Init(AnsiString,AnsiString); void InitComponent(void); bool LoadFromFile(bool); void SaveToFile(void); bool Add(void); void ShowValue(void); bool Modify(void); bool Delete(void); void SetSearchComponentsVisible(AnsiString,AnsiString,AnsiString,AnsiString); SFIELD& FieldByName(AnsiString); SFIELD& FieldByCName(AnsiString); void Search(AnsiString,AnsiString); }; //--------------------------------------------------------------------------- 写到后来发现其实在IOP的函数完全可以在TRecordActive中定义,甚至可以不用定义成虚函数,只是普通函数让后代有必要的话重载就可以了,虚函数在这里没有起到太大的作用,只是结构清晰点而已,也似乎在这种情况下才有点用: class IA { ... virtual void DOSOMETING(){}; } TForm1:public TForm,IA { ... void DOSOMETING() { do someting; } } ..... void F(IA *A) { IA->DOSOMETING(); } TForm::Show(...) { TA a=new TA(); F(this); } 但不太实用,虽越来越喜欢用虚的,但不得精髓,容易画蛇添足 ,在什么情况下用虚函数,而什么情况下用重载好呢?,或者说也看到了虚函数的好处和未来升格成一个COM系统开发员的前景,但还是意识模糊
ilikeff8
一般會員


發表:12
回覆:16
積分:5
註冊:2002-12-28

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-06-10 16:10:10 IP:218.0.xxx.xxx 未訂閱
TRecordActive是父类
brant
一般會員


發表:1
回覆:64
積分:23
註冊:2003-04-07

發送簡訊給我
#3 引用回覆 回覆 發表時間:2003-06-11 10:36:25 IP:61.219.xxx.xxx 未訂閱
寫一個簡單的例子給你:
 
#include <iostream>
using namespace std;    class A {
public:
//void AA(){cout<<"I am A"<AA();
}    void main()
{
        B b;
        C c;            test(&b);
        test(&c);
}
把class A對AA()的宣告互換試一下 你應該就能知道什麼時候要用 virtual function 了。 (記得把大小於箭頭改成半型的) 發表人 - brant 於 2003/06/11 10:41:10
ilikeff8
一般會員


發表:12
回覆:16
積分:5
註冊:2002-12-28

發送簡訊給我
#4 引用回覆 回覆 發表時間:2003-06-12 09:26:10 IP:218.0.xxx.xxx 未訂閱
引言: 寫一個簡單的例子給你:
 
#include <iostream>
using namespace std;    class A {
public:
//void AA(){cout<<"I am A"<AA();
}    void main()
{
        B b;
        C c;            test(&b);
        test(&c);
}
把class A對AA()的宣告互換試一下 你應該就能知道什麼時候要用 virtual function 了。 (記得把大小於箭頭改成半型的) 發表人 - brant 於 2003/06/11 10:41:10
你这个例子很好,理顺里一下头绪,虽然一直在用虚函数的功能,但一直把它与重载的功能原理搞混了 class A { public: /*virtual*/ void AA(void){ ShowMessage("A") ; } }; class B:public A { public: void AA(void); }; class C:public A { public: void AA(void); }; void B::AA(void) { ShowMessage("B"); }; void C::AA(void) { ShowMessage("C"); }; void test(A *a) { a->AA(); }; ... void __fastcall TForm1::Button1Click(TObject *Sender) { B b; C c; test(&b); test(&c); } 如果没有加virtual, test(&b); test(&c); 都只会调用父类的AA 只有加上virtual 才能调用它们自己的AA 是否可以这样理解: 重载只是让后代能使用父类的功能,遇上同名将忽略后代同名方法 而虚函数可能让后代改写父类的功能,遇上同名将忽略父代同名方法,但可以Inherited 理了下思路,往往东西做出来了事后却忘了自己是怎么做的,真倒
brant
一般會員


發表:1
回覆:64
積分:23
註冊:2003-04-07

發送簡訊給我
#5 引用回覆 回覆 發表時間:2003-06-12 12:12:31 IP:61.219.xxx.xxx 未訂閱
您的理解很正確 這樣的用法,叫做「多型」(polymorphism) 虛擬與多型,通常是一體兩面 發表人 - brant 於 2003/06/12 12:21:29
ilikeff8
一般會員


發表:12
回覆:16
積分:5
註冊:2002-12-28

發送簡訊給我
#6 引用回覆 回覆 發表時間:2003-06-12 13:26:07 IP:218.0.xxx.xxx 未訂閱
推而广之,我想应该可以用在这种场合: 版权:试用版,对某功能进行限制 //--------------------------------------------------------------------------- //#define DemoVersion class TA { public: #ifndef DemoVersion virtual #endif void DOSOMETING(void); }; //--------------------------------------------------------------------------- class TB:public TA { public: void DOSOMETING(void); }; //--------------------------------------------------------------------------- void TA::DOSOMETING(void) { ShowMessage("This Version can't use this function."); } //--------------------------------------------------------------------------- void TB::DOSOMETING(void) { ShowMessage("!"); } //--------------------------------------------------------------------------- void DoFunction(TA *A) { A->DOSOMETING(); } //--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { TB *B=new TB(); DoFunction(B); } //---------------------------------------------------------------------------
brant
一般會員


發表:1
回覆:64
積分:23
註冊:2003-04-07

發送簡訊給我
#7 引用回覆 回覆 發表時間:2003-06-12 23:46:11 IP:61.219.xxx.xxx 未訂閱
是可以這樣用沒錯啦 但這不是C++所定義這個關鍵字及語法的原義 重點在polymorphism    我之前已經講了 virtual跟polymorphism是一體兩面 polymorphism就是以父類的介面 事實上去調用子類的操作 這在一個父類有很多種子類 都有一種共同的操作時 只要把子類轉型成父類去呼叫該操作 就會調用到子類的操作而不會去調用到父類的操作 進而就可以用同一個函數當入口 將參數宣告成父類(就像我舉例的test(A* a)) 然後在裡面用父類的介面直接呼叫 不用再去判斷以父類傳進來的類別是哪個子類 再去轉成子類,再去調到需要的成員函數 或是將子類轉型成父類去調用該操作 而不用管這個子類到底是哪種子類 這樣寫出來的程式碼會比較好懂比較優雅 譬如說定義一種父類叫 airplane 有一個操作叫 fly 然後可以有 plane747、planeF16、planeIDF、smallplane四種類去繼承airplane 這四種飛機的飛法都不一樣 然後我們用某種法式產生了這四種飛機各若干架 都在天空飛,方向、速度都不同 但這些飛機都放在一個 airplane * 的 link list裡面 有一個timer,每一秒更新這些飛機的位置 就需要把這個list從頭到尾跑一遍 一一呼叫它們的fly 如果airplane的fly不是virtual,那一叫它們的fly就只會照原本airplane定義的飛法在飛 如果要分別判斷目前的airplane是哪種子類,再轉型去呼叫正確的fly 程式碼又臭又長,效率又不好 所以就需要把airplane的fly宣告為virtual 這樣就可以在尋訪這個list的時候 把各種飛機都當作是飛機,只要叫它飛 它自己會照它自己的方式去飛 我們不需要知道它是哪種飛機 程式碼寫起來只是短短幾行 也少了很多型別的判斷,效率也比較好 如果您還是想不通我所說的 建議您在polymorphism這方面下點工夫 發表人 -
ilikeff8
一般會員


發表:12
回覆:16
積分:5
註冊:2002-12-28

發送簡訊給我
#8 引用回覆 回覆 發表時間:2003-06-13 14:11:40 IP:218.0.xxx.xxx 未訂閱
引言: 是可以這樣用沒錯啦 但這不是C 所定義這個關鍵字及語法的原義 重點在polymorphism 我之前已經講了 virtual跟polymorphism是一體兩面 polymorphism就是以父類的介面 事實上去調用子類的操作 這在一個父類有很多種子類 都有一種共同的操作時 只要把子類轉型成父類去呼叫該操作 就會調用到子類的操作而不會去調用到父類的操作 進而就可以用同一個函數當入口 將參數宣告成父類(就像我舉例的test(A* a)) 然後在裡面用父類的介面直接呼叫 不用再去判斷以父類傳進來的類別是哪個子類 再去轉成子類,再去調到需要的成員函數 或是將子類轉型成父類去調用該操作 而不用管這個子類到底是哪種子類 這樣寫出來的程式碼會比較好懂比較優雅 譬如說定義一種父類叫 airplane 有一個操作叫 fly 然後可以有 plane747、planeF16、planeIDF、smallplane四種類去繼承airplane 這四種飛機的飛法都不一樣 然後我們用某種法式產生了這四種飛機各若干架 都在天空飛,方向、速度都不同 但這些飛機都放在一個 airplane * 的 link list裡面 有一個timer,每一秒更新這些飛機的位置 就需要把這個list從頭到尾跑一遍 一一呼叫它們的fly 如果airplane的fly不是virtual,那一叫它們的fly就只會照原本airplane定義的飛法在飛 如果要分別判斷目前的airplane是哪種子類,再轉型去呼叫正確的fly 程式碼又臭又長,效率又不好 所以就需要把airplane的fly宣告為virtual 這樣就可以在尋訪這個list的時候 把各種飛機都當作是飛機,只要叫它飛 它自己會照它自己的方式去飛 我們不需要知道它是哪種飛機 程式碼寫起來只是短短幾行 也少了很多型別的判斷,效率也比較好 而且用多型,往後的擴充性比較好: 以後如果發明了一種飛機叫 tirtleplane 也只要繼承 airplane,設計出飛得很龜的 fly 然後同樣丟到那個 list 裡面去 其他地方的程式碼都不用改 天空中就可以多一種很龜的飛機在飛來飛去 於是天空中就有飛得很龜的 也有飛得很快的飛機了 如果您還是想不通我所說的 建議您在polymorphism這方面下點工夫 發表人 - >< face="Verdana, Arial, Helvetica"> 你讲的是没错拉,而我讲的是比较另类的一种“用法”而已
brant
一般會員


發表:1
回覆:64
積分:23
註冊:2003-04-07

發送簡訊給我
#9 引用回覆 回覆 發表時間:2003-06-13 15:44:38 IP:61.219.xxx.xxx 未訂閱
C 的語法都有一定的意義 設計一個class,如果利用這些語法 明確表達出這個class的理念 他人只要看這個class的宣告 就可以了解作者寫這個class的用法及目的 這點是很重要的 如果您喜歡用另類的用法 以後要維護您程式的人 只會增加他們晚上的失眠指數罷了 也有可能是您自己哦 在業界很有可能會拿出一年前寫的程式要修改 而且這樣寫出來的class,重用性不高
ilikeff8
一般會員


發表:12
回覆:16
積分:5
註冊:2002-12-28

發送簡訊給我
#10 引用回覆 回覆 發表時間:2003-06-14 02:44:06 IP:203.175.xxx.xxx 未訂閱
引言: C 的語法都有一定的意義 設計一個class,如果利用這些語法 明確表達出這個class的理念 他人只要看這個class的宣告 就可以了解作者寫這個class的用法及目的 這點是很重要的 如果您喜歡用另類的用法 以後要維護您程式的人 只會增加他們晚上的失眠指數罷了 也有可能是您自己哦 在業界很有可能會拿出一年前寫的程式要修改 而且這樣寫出來的class,重用性不高
的确,这是我突发其想,是没多大实用意义
系統時間:2024-05-18 7:03:59
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!