青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

Benjamin

靜以修身,儉以養德,非澹薄無以明志,非寧靜無以致遠。
隨筆 - 398, 文章 - 0, 評論 - 196, 引用 - 0
數據加載中……

深度理解C++概念之繼承(二)

1.有關 private virtuals:幾乎不用。如果沒有特殊的原因,不提倡使用。
2.當基類構造函數調用虛函數時,為什么不調用派生類重寫的該虛函數?這樣做是危險的,C++會阻止你這樣做
coder:
#include <iostream>
 #include <string>
 
 void println(const std::string& msg)
 { std::cout << msg << '\n'; }
 
 class Base {
 public:
   Base()              { println("Base::Base()");  virt(); }
   virtual void virt() { println("Base::virt()"); }
 };
 
 class Derived : public Base {
 public:
   Derived()           { println("Derived::Derived()");  virt(); }
   virtual void virt() { println("Derived::virt()"); }
 };
 
 int main()
 {
   Derived d;
   ...
 }
程序輸出:

 Base::Base()
 Base::virt() // ← Not Derived::virt()
 Derived::Derived()
 Derived::virt()
 
當基類被構造時,對象還不是一個派生類的對象,所以如果 Base::Base()調用了虛函數 virt(),則 Base::virt() 將被調用,即使 Derived::virt()(即派生類重寫的虛函數)存在。
同樣,當基類被析構時,對象已經不再是一個派生類對象了,所以如果 Base::~Base()調用了virt(),則 Base::virt()得到控制權,而不是重寫的 Derived::virt() 。
如果 Base::Base()調用了虛函數 virt(),這個規則使得 Base::virt()被調用。如果不按照這個規則,Derived::virt()將在派生對象的派生部分被構造之前被調用,此時屬于派生對象的派生部分的某個成員對象還沒有被構造,而 Derived::virt()卻能夠訪問它。這將是災難。
3.模擬動態綁定在一個基類的構造里的方法
class Base {
 public:
   Base();
   ...
   virtual void foo(int n) const; // often pure virtual
   virtual double bar() const;    // often pure virtual
   // if you don't want outsiders calling these, make them protected
 };
 
 Base::Base()
 {
   ... foo(42) ... bar() ...
   // these will not use dynamic binding
   // goal: simulate dynamic binding in those calls
 }
 
 class Derived : public Base {
 public:
   ...
   virtual void foo(int n) const;
   virtual double bar() const;
 };
實現方法有兩種,根據自己實際情況來選擇。
第一種方法,把初始化分兩個階段,第一階段是實際的構造,第二階段是"init"方法。動態綁定就在第二階段,第二階段是構造概念的一部分,所以我們可以簡單的把從 Base::Base() 移到 Base::init()
class Base {
 public:
   void init();  // may or may not be virtual
   
...
   virtual void foo(int n) const; 
// often pure virtual
   virtual double bar() const;    
// often pure virtual
 };
 
 void Base::init()
 {
   
... foo(42) ... bar() ...
   
// most of this is copied from the original 
Base::Base()
 }
 
 class Derived : public Base {
 public:
   
...
   virtual void foo(int n) const;
   virtual double bar() const;
 };
剩下的就是確定哪里調用第一階段,哪里調用第二階段。這里我們要注意以下兩點:第一在創建對象時,要加上小小的約束條件,尤其在同一層中有一處或兩處要創建
創建時,這個約束可以確保程序不會出錯。第二在第一階段創建對象的方法有三種,是new Derived或是聲明
Derived對象,或是不知道具體的類型(通過虛構造或
類工廠創建),用第三種是強壯的,這樣可是你很容易的插入一個Derived對象。
在第一階段,對象的創建一般在堆上,這時我們需要保存一個管理指針(智能指針
std::auto_ptr,引用計數的指針,或是其他的析構刪除),最好的預防堆溢出的方法是在第二階段是拋出異常。分配堆空間簡單的示例代碼如下:
#include <memory>
 
 void joe_user()
 {
   std::auto_ptr<Base> p(/*...somehow create a Derived object via new...*/);
   p->init();
   
...
 }

第二種方案是組合joe_user前兩句到create函數里。如果你是用工廠(factory)模式,譬如虛構造,你可以這兩行放在靜態方法中調用Base::create(): 代碼如下
#include <memory>
 
 class Base {
 public:
   ...
   typedef std::auto_ptr<Base> Ptr;  
// typedefs simplify the code
   static Ptr create();
   
...
 };
 
 Base::Ptr Base::create()
 {
   Ptr p(
/*...use a factory to create a Derived object via new...*/);
   p->init();
   return p;
 }
它簡化了joe_user的功能,更重要的是可以在創建對象不用調用Init().
void joe_user()
 {
   Base::Ptr p = Base::create();
   ...
 }
我們在這個方法中,我們應當竭力避免調用Init(),那么就應該使派生類的構造、拷貝構造成為priviate或protected;

最后的方法,則和上面的都不同,在第二層類結構中加入foo()和
bar(). 如果這兩個函數要存取Derived的數據時,這個方法是不能用的。
class Helper {
 public:
   virtual void foo(int n) const = 0;
   virtual double bar() const = 0;
 };
 
 class Helper1 : public Helper {
 public:
   virtual void foo(int n) const;
   virtual double bar() const;
 };
 
 class Helper2 : public Helper {
 public:
   virtual void foo(int n) const;
   virtual double bar() const;
 };
Base類也要刪除init(),Base類和Derived類要刪除foo() and
bar(),在Base類構造中加入Helper的引用 
 class Base {
 public:
   Base(const Helper& h);
   ...   
// remove 
   
...   
// remove 
 };
 
 class Derived : public Base {
 public:
   
...   
// remove 
 };
當我們定義Base::Base(const Helper&)時,它會正確調用h.foo(42)和
h.bar()
 Base::Base(const Helper& h)
 {
   ... h.foo(42) ... h.bar() ...

   
// almost identical to the original 
Base::Base()
   
// but with 
h. in calls to h.foo() and h.bar()
 }
Derived::Derived()
   : Base(Helper2())   // the magic happens here

 {
   
...
 }

注意:Derived可以傳遞值到Helper的派生類的構造中,但不是任何的數據都可以傳至Helper派生類。比如Helper::foo()和
Helper::bar() 就不能存取數據在這個類中,特別是數據是Derived類中中聲明的數據。

Helper派生類也可以做成類似joe_user功能,例如:
Derived::Derived(const Helper& h)
   : Base(h)
 {
   ...

 }
如果Helper不需要數據,那么可以通過一個靜態方法來替代它。
class Base {
 public:
   typedef void (*FooFn)(int);  // typedefs simplify

   typedef double (*BarFn)();   
//    the rest of the code
   Base(FooFn foo, BarFn bar);
   
...
 };
 
 Base::Base(FooFn foo, BarFn bar)
 {
   
... foo(42) ... bar() ...
   
// almost identical to the original 
Base::Base()
   
// except calls are made via function pointers.
 }
class Derived : public Base {
 public:
   Derived();
   static void foo(int n); // the static is important!

   static double bar();    
// the static is important!
   
...
 };
 
 Derived::Derived()
   : Base(foo, bar)  
// pass the function-ptrs into Base's ctor
 {
   
...
 }






posted on 2009-07-04 15:51 Benjamin 閱讀(290) 評論(0)  編輯 收藏 引用


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            久久精品人人做人人爽电影蜜月| 亚洲欧美日韩第一区| 久久亚洲综合网| 欧美一级午夜免费电影| 国产深夜精品福利| 久久久久久久波多野高潮日日| 欧美一区二区三区视频在线观看| 国产农村妇女毛片精品久久莱园子| 午夜精品区一区二区三| 欧美一区中文字幕| 亚洲国产毛片完整版| 91久久黄色| 欧美视频免费| 久久久久免费视频| 欧美成人性生活| 亚洲尤物精选| 久久精品欧美| 一区二区三区成人| 欧美一区二区日韩| 亚洲美女尤物影院| 午夜精品在线观看| 亚洲欧洲在线视频| 亚洲性线免费观看视频成熟| 狠狠色伊人亚洲综合网站色 | 伊人婷婷欧美激情| 欧美激情网友自拍| 国产精品av免费在线观看| 久久精品导航| 欧美二区在线播放| 一本一本久久a久久精品综合妖精 一本一本久久a久久精品综合麻豆 | 亚洲美女免费精品视频在线观看| 欧美香蕉大胸在线视频观看| 久久免费偷拍视频| 欧美日韩国产成人精品| 久久精品男女| 欧美日韩国产一区二区三区地区| 久久国产精品99久久久久久老狼| 免费亚洲婷婷| 久久精品人人做人人综合 | 亚洲婷婷综合久久一本伊一区| 国产自产高清不卡| 99精品欧美一区| 亚洲福利专区| 欧美一区观看| 亚洲综合色在线| 欧美高清在线播放| 免费欧美在线| 国内精品免费午夜毛片| 99视频在线精品国自产拍免费观看 | 亚洲欧美日本国产有色| 亚洲精品国产精品国自产观看浪潮 | 欧美国产三级| 国内综合精品午夜久久资源| 制服丝袜亚洲播放| 中文有码久久| 欧美人与性动交a欧美精品| 欧美成人精品1314www| 国产美女诱惑一区二区| 一区二区三区精品| 亚洲日本中文字幕| 欧美大片免费观看| 欧美黑人国产人伦爽爽爽| 一区二区在线免费观看| 西西裸体人体做爰大胆久久久| 亚洲视频免费观看| 欧美激情小视频| 亚洲国产精品成人综合色在线婷婷| 国产一区在线播放| 亚洲欧美视频一区二区三区| 亚洲欧美日本精品| 国产精品视频久久一区| 亚洲在线成人精品| 欧美一级视频| 国产日韩在线看| 欧美一区二区视频免费观看| 久久久九九九九| 激情综合在线| 欧美成人中文| 亚洲啪啪91| 亚洲一区二区精品在线观看| 欧美日韩伦理在线| 亚洲欧美日韩国产另类专区| 欧美在线观看视频| 一区国产精品| 欧美激情网友自拍| 中文在线不卡| 久久久久久久一区二区| 在线观看视频一区二区欧美日韩 | 亚洲国产另类久久久精品极度| 亚洲国产天堂久久综合网| 欧美激情国产日韩| 亚洲午夜激情| 老司机免费视频久久| 亚洲精品一区在线观看| 欧美三级欧美一级| 久久er99精品| 亚洲激情自拍| 久久激情视频| 亚洲精品综合| 国产精品一区在线播放| 久久五月婷婷丁香社区| 亚洲成人资源网| 亚洲欧美日韩精品久久奇米色影视 | 久久国产福利国产秒拍| 欧美成人午夜影院| 午夜精品久久久久久99热软件| 国产一区二区三区高清播放| 你懂的国产精品| 亚洲在线视频免费观看| 欧美成人精品1314www| 亚洲一区制服诱惑| 国产一区二区三区免费在线观看| 农夫在线精品视频免费观看| 一区二区三区高清不卡| 久久综合网色—综合色88| 亚洲一区欧美二区| 亚洲欧洲日本在线| 国模 一区 二区 三区| 欧美日韩国产999| 久久九九99| 午夜亚洲福利在线老司机| 亚洲人成网站777色婷婷| 久久av最新网址| 亚洲视频免费| 亚洲第一区在线| 国产午夜精品视频免费不卡69堂| 欧美日韩成人综合在线一区二区 | 99re视频这里只有精品| 免费91麻豆精品国产自产在线观看| 亚洲女同精品视频| 一本色道88久久加勒比精品| 在线观看av不卡| 黑丝一区二区| 国产无遮挡一区二区三区毛片日本| 欧美欧美天天天天操| 欧美凹凸一区二区三区视频| 久久精品国产91精品亚洲| 亚洲在线中文字幕| 99综合电影在线视频| 亚洲精品亚洲人成人网| 亚洲国产日韩在线| 亚洲第一精品久久忘忧草社区| 久久久噜噜噜久噜久久 | 在线免费观看一区二区三区| 国产三区二区一区久久| 国产精品久久久久久久久久直播| 欧美三级视频在线播放| 欧美日一区二区在线观看 | 鲁鲁狠狠狠7777一区二区| 久久婷婷国产综合尤物精品 | 亚洲日本在线观看| 最近中文字幕日韩精品 | 亚洲精品精选| 99精品国产一区二区青青牛奶| 亚洲国产一区二区三区在线播| 欧美国产一区在线| 91久久精品国产91久久| 亚洲黄色在线视频| 一本高清dvd不卡在线观看| 一区二区激情视频| 亚洲资源av| 欧美在线电影| 蜜臀av一级做a爰片久久| 欧美精品在线视频观看| 欧美日韩视频一区二区| 国产精品视频第一区| 国产一区二区三区日韩欧美| 国产在线乱码一区二区三区| 在线日本成人| 亚洲最新合集| 午夜日韩福利| 免费久久精品视频| 亚洲精品国久久99热| 亚洲一区二区av电影| 欧美亚洲免费在线| 美女图片一区二区| 欧美视频官网| 在线观看成人av| 亚洲一区图片| 免费成人小视频| 野花国产精品入口| 久久精品国产亚洲精品| 欧美福利小视频| 国产日韩精品视频一区二区三区 | 国产精品午夜在线| 亚洲国产精品电影| 亚洲综合日韩在线| 欧美成人xxx| 亚洲专区一区| 欧美精品久久久久久久久久| 国产日韩欧美在线视频观看| 亚洲精品乱码久久久久久| 午夜精品一区二区三区电影天堂| 麻豆精品在线观看| 亚洲综合日韩| 欧美.www| 影音国产精品| 欧美在线1区| 99国产精品久久久久老师| 久久久青草婷婷精品综合日韩|