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

            C+之父力作學習筆記6——派生類

                  現在來考慮做一個程序,處理某公司所雇傭人員的問題。這個程序可能包含如下一種數據結構:
            struct Employee
            {
                
            string first_name,family_name;
                
            char middle_initial;
                Date hiring_date;
                
            short department;
                
            //
            }
            ;
            下一步我們可能需要去定義經理:
            struct Manager
            {
                Employee emp;
                list
            <Employee*> group; //所管理的人員
                short level;
                
            //
            }
            ;
            一個經理同時也是一個雇員,所以在Manager對象的emp成員存儲著Employee數據。很明顯這樣的設計是糟糕的,大家都會想到派生:
            struct Manager:public Employee
            {
                list
            <Employee*> group;
                
            short level;
            }
            ;
            這個Manager是由Employee派生的,反過來就是說,Employee是Manager的一個基類。類Manager包含類Employee得所有成員,再加上它自己的一些成員。
                  按照這種方式從Employee派生出Manager,就使Manager成為Employee的一個子類型,使Manager可以用在能夠接受Employee的任何地方。因為Manager是Employee,所以Manager*就可以當做Employee*使用。然而,因為Employee不一定是Manager,所以Employee*就不能當做Manager*用。總而言之類Derived有一個公用基類Base,那么就可以用Derived*給Base*類型的變量賦值,不需要顯示的類型轉換。而相反的方向,從Base*到Derived*則必須顯示轉換。例如:
            void g(Manager mm,Employee ee)
            {
                Employee
            * pe = &mm;  //可以:Manager都是Employee
                Manager* pm = &ee;   //錯誤:Employee不一定是Manager
                pm->level = 2;       //災難:ee沒有level
                pm = static_cast<Manager*>(pe);//蠻力:這個可以,因為pe指向的是Manager mm
                pm->level = 2;       //沒問題
            }

                  派生類的成員可以使用其基類的公用的和保護的成員,但是,派生類不能使用基類的私有成員。對于派生類的成年公園而言,保護成員就像是公用成員;但對于其他函數它們則像是私用成員。
                  下面說說派生類的構造函數和析構函數
                  有些派生類需要構造函數。如果某個基類中有構造函數,那么就必須調用這些構造函數中的某一個。默認構造函數可以被隱含的調用,但是,如果一個基類的所有構造函數都有參數,那么就必須顯示的調用其中的某一個?;悩嬙旌瘮档膮祽谂缮悩嬙旌瘮档亩x中有明確描述。在這方面,基類的行為恰恰就像是派生類的一個成員。例如:
            Employee::Employee(const string& n,int d):family(n),department(d)
            {
                
            //
            }


            Manager::Manager(
            const string& n,int d,int lvl):Employee(n,d),/*初始化基類*/level(lvl)/*初始化成員*/
            {
                
            //
            }
            派生類的構造函數只能描述它自己的成員和自己的直接基類的初始式,它不能直接去初始化基類的成員,例如:
            Manager::Manager(const string& n,int d,int lvl):family_name(n).department(d),level(lvl)//錯誤:在Manager里沒有family_name和department的聲明
            {
            //
            }
             類對象的構造是自下而上進行的:首先是基類,而后是成員,再后才是派生類本身。類對象的銷毀則正好以相反的順序進行:首先是派生類本身,而后是成員,再后才是基類。
                  對于給定的一個類型為Base*的指針,被指的對象到底屬于哪個派生類型呢?這個問題有四種基本的解決方案:
            1.  保證被指的只能是唯一類型的對象
            2. 在基類里安排一個類型域,供函數檢查
            3.  使用dynamic_cast
            4.  使用虛函數  

                   從Employee的函數中取得“正確的”行為i,而又不依賴于實際使用的到底是哪一種Employee,這就是所謂的多態性。一個帶有虛函數的類型被稱為是一個多態類型。要在C++里取得多態行為,被調用的函數就必須是虛函數,而對象則必須是通過指針或者引用去操作的。如果直接操作一個對象(而不是通過指針或引用),它的確切類型就已經為編譯器所知,因此也就不需要運行時的多態性了。
                  那么一個虛函數聲明為純虛函數,則這個虛函數所在的類為抽象類。用=0作為初始式就使虛函數成為“純虛的”。注意:不能創建抽象類的對象。抽象類只能做界面,作為其他類的基類。還有一點也要指的注意,一個未在派生類里定義的純虛函數仍舊還是一個純虛函數,這種情況也將使該派生類仍為一個抽象類。例如:

            class Shape
            {
                 
            public:
                    
            virtual void draw()=0;
                    
            virtual bool isClose()=0;
                 
            //
            }
            ;

            class Circel:public Shape
            {
                
            public:
                   
            bool isClose(){return true;}//覆蓋Shap::isClose
                   
            //draw尚未覆蓋
            }
            ;

            Circel a;//錯誤:聲明的是抽象類Circel對象

            抽象類的最重要用途就使提供一個界面,而又不是暴露任何實現的細節。
                  
                 忠告 :

            • 避免類型域
            • 用抽象類將設計的中心集中到提供清晰的界面方面
            • 用抽象類使界面最小化
            • 一個有虛函數的類應該有一個虛析構函數
            • 抽象類通常不需要構造函數

            posted on 2011-08-28 17:20 Daywei 閱讀(2000) 評論(0)  編輯 收藏 引用 所屬分類: C++之父力作學習筆記

            <2011年8月>
            31123456
            78910111213
            14151617181920
            21222324252627
            28293031123
            45678910

            導航

            統計

            常用鏈接

            留言簿

            隨筆分類

            隨筆檔案

            文章檔案

            牛人博客

            搜索

            積分與排名

            最新評論

            閱讀排行榜

            亚洲AV无码1区2区久久| 亚洲国产欧洲综合997久久| 久久久av波多野一区二区| 国色天香久久久久久久小说| 午夜精品久久久久久影视777| 国产精品成人久久久久久久| 亚洲精品成人久久久| 久久久久国产一级毛片高清板| 午夜肉伦伦影院久久精品免费看国产一区二区三区| 狠狠色婷婷久久一区二区三区 | 久久亚洲高清综合| 狠狠色噜噜色狠狠狠综合久久| 久久AV高潮AV无码AV| 久久精品中文字幕有码| 狠狠色丁香婷婷久久综合五月| 久久99国产精品久久99| 久久久久人妻精品一区二区三区| 久久精品亚洲福利| 久久久久久国产精品无码下载| 久久久久久夜精品精品免费啦| 久久久亚洲精品蜜桃臀| 日本精品久久久久中文字幕8| 久久精品aⅴ无码中文字字幕不卡| 久久夜色精品国产www| 91精品久久久久久无码| 嫩草影院久久国产精品| 91久久精品无码一区二区毛片| 精品久久久无码中文字幕天天| 2022年国产精品久久久久 | 亚洲国产一成人久久精品| 无码超乳爆乳中文字幕久久| 国产亚洲色婷婷久久99精品91| 久久综合综合久久狠狠狠97色88| 久久夜色精品国产噜噜噜亚洲AV| 久久国产免费直播| 2021精品国产综合久久| 亚洲&#228;v永久无码精品天堂久久| 亚洲午夜福利精品久久| 日本免费久久久久久久网站| 亚洲愉拍99热成人精品热久久 | 亚洲性久久久影院|