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

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 閱讀(288) 評論(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>
            欧美日韩中文字幕综合视频| 久久久久久久久久看片| 欧美视频日韩视频在线观看| 久久天堂国产精品| 久久婷婷久久| 麻豆精品一区二区av白丝在线| 欧美有码在线观看视频| 久久精品综合一区| 免费观看日韩| 欧美激情麻豆| 国产日产欧美精品| 亚洲精品欧美日韩专区| 中文久久精品| 久久久97精品| 91久久国产综合久久91精品网站| 最新国产乱人伦偷精品免费网站| 亚洲激情啪啪| 久久久人成影片一区二区三区观看 | 亚洲国产高潮在线观看| 亚洲欧洲在线一区| 亚洲在线免费视频| 欧美激情中文字幕一区二区| 一本色道久久99精品综合| 久久精品国产99国产精品| 欧美日韩一区二区三区视频 | 欧美大成色www永久网站婷| 欧美日韩日本国产亚洲在线 | 欧美好吊妞视频| 亚洲国产综合在线| 美女亚洲精品| 欧美一级大片在线观看| 国产精品福利在线| 亚洲综合色婷婷| 国产精品99久久久久久人| 欧美人与性动交a欧美精品| 亚洲第一精品夜夜躁人人爽| 久久亚洲不卡| 欧美aa在线视频| 日韩一区二区免费高清| 亚洲国产天堂久久综合网| 免费观看一区| 日韩一级视频免费观看在线| 亚洲精品久久久久久一区二区| 免费看亚洲片| 宅男噜噜噜66国产日韩在线观看| 亚洲精品欧美在线| 国产精品盗摄一区二区三区| 亚洲欧美网站| 久久中文精品| 午夜精品久久久久久久久久久久| 一区二区福利| 日韩小视频在线观看专区| 国产精品国产一区二区| 久久国产乱子精品免费女| 久久亚洲一区二区| 一区二区三区成人| 看片网站欧美日韩| 亚洲欧美国产日韩中文字幕| 欧美在线视频a| 亚洲午夜av在线| 美女爽到呻吟久久久久| 亚洲欧美日韩直播| 免费视频一区| 美女成人午夜| 国产精品自拍视频| 99riav国产精品| 亚洲精品久久视频| 久久手机免费观看| 久久婷婷丁香| 国产一区日韩欧美| 亚洲欧美不卡| 欧美伊人久久久久久午夜久久久久| 免费观看日韩av| 亚洲成人中文| 亚洲精选91| 欧美视频在线观看一区二区| 亚洲破处大片| 一本久久综合亚洲鲁鲁五月天| 美国十次成人| 日韩视频一区二区在线观看| 亚洲国产高清在线| 裸体一区二区| 亚洲国产精品t66y| 一本色道久久综合狠狠躁的推荐| 欧美电影免费网站| 99视频精品| 欧美激情区在线播放| 欧美va天堂| 日韩亚洲欧美中文三级| 亚洲神马久久| 在线日韩av| 欧美日韩在线免费| 久久不射中文字幕| 亚洲免费精彩视频| 免费日韩视频| 欧美在线观看你懂的| 亚洲人午夜精品免费| 国产精品久久国产愉拍 | 欧美中文字幕视频在线观看| 国产欧美一区二区三区在线看蜜臀| 香蕉久久一区二区不卡无毒影院 | 日韩视频―中文字幕| 久久久精品国产99久久精品芒果| 亚洲国产高清高潮精品美女| 国产精品自拍三区| 国产精品久久久久永久免费观看| 免费亚洲婷婷| 欧美顶级少妇做爰| 亚洲剧情一区二区| 亚洲精品国精品久久99热一| 国产在线播放一区二区三区| 国产精品黄视频| 国产日韩精品一区二区| 国产精品男女猛烈高潮激情| 欧美人与性动交a欧美精品| 欧美成人免费观看| 欧美激情2020午夜免费观看| 老司机精品久久| 免费一级欧美在线大片| 久久综合五月天婷婷伊人| 久久综合五月| 欧美日韩国语| 国产欧美日韩在线| 亚洲欧美日韩直播| 日韩一二三在线视频播| 在线中文字幕一区| 久久爱www久久做| 欧美α欧美αv大片| 欧美日韩在线直播| 国产一区清纯| 亚洲三级视频在线观看| 亚洲欧美国产77777| 免费观看不卡av| 一本一本a久久| 欧美不卡视频一区| 国产三级欧美三级| 一本久久综合亚洲鲁鲁五月天| 午夜亚洲性色福利视频| 欧美 日韩 国产 一区| 夜夜嗨av一区二区三区四区 | 午夜老司机精品| 欧美激情按摩| 久久久欧美一区二区| 国产精品中文字幕欧美| 99精品欧美一区二区蜜桃免费| 午夜精品在线视频| 亚洲久久成人| 欧美日韩精品一区二区三区四区| 国内精品国产成人| 欧美在线视频在线播放完整版免费观看 | 亚洲欧美另类中文字幕| 嫩草影视亚洲| 在线欧美日韩国产| 亚洲福利在线观看| 欧美国产日韩免费| 日韩一区二区电影网| 亚洲激情欧美| 国产精品久久777777毛茸茸| 亚洲自拍电影| 亚洲欧美文学| 玖玖玖国产精品| 久久av一区二区三区漫画| av成人免费在线| 欧美高清不卡在线| 99视频精品免费观看| 欧美日韩和欧美的一区二区| 在线亚洲欧美| 亚洲免费小视频| 一色屋精品亚洲香蕉网站| 女同一区二区| 国产精品色午夜在线观看| 久久婷婷激情| 国产精品日本| 最新成人在线| 国产精品视频第一区| 亚洲专区欧美专区| 久久视频国产精品免费视频在线| 亚洲国产三级| 午夜精品影院| 亚洲精选成人| 你懂的国产精品| 久久人体大胆视频| 国产精品一区二区三区观看| 亚洲国产欧美不卡在线观看| 国产亚洲永久域名| 午夜欧美理论片| 欧美一区二区福利在线| 欧美手机在线| 日韩视频免费观看高清完整版| 亚洲欧洲在线免费| 男女精品视频| 亚洲激情第一页| 亚洲三级电影全部在线观看高清| 欧美在线高清视频| 久久久久高清| 欲香欲色天天天综合和网| 久久精品国产欧美激情| 久热精品视频在线观看| 伊人久久婷婷色综合98网| 久久久五月天|