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

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>
            亚洲欧美中文另类| 亚洲黄色成人久久久| 国产精品美女一区二区| 国产精品亚洲美女av网站| 黄色国产精品| 日韩亚洲在线观看| 午夜国产不卡在线观看视频| 久久久久女教师免费一区| 亚洲福利小视频| 亚洲三级免费电影| 亚洲小说春色综合另类电影| 欧美在线视频观看| 亚洲三级网站| 久久精品国产一区二区三| 欧美国产先锋| 国外成人在线视频| 亚洲国产一区二区a毛片| 亚洲欧美日韩另类精品一区二区三区| 国产精品手机视频| 老司机一区二区三区| 亚洲午夜精品久久久久久app| 久久男人资源视频| 国产偷国产偷精品高清尤物| 一本大道久久a久久精二百| 女人色偷偷aa久久天堂| 亚洲永久在线观看| 国产精品久久网| 欧美不卡视频一区发布| 欧美午夜性色大片在线观看| 亚洲国产综合在线看不卡| 一本色道久久综合亚洲二区三区| 美女精品自拍一二三四| 国产视频一区免费看| 亚洲第一视频| 国产日韩精品久久| 亚欧成人在线| 亚洲视频欧洲视频| 国产精品久久久久久五月尺| 欧美成人资源网| 久久国产欧美| 精品二区久久| 免费的成人av| 欧美电影资源| 亚洲最新视频在线| 久久久蜜臀国产一区二区| 国外成人在线视频网站| 一区二区久久| 一区二区欧美在线| 亚洲视频免费在线| 亚洲美女在线看| 一区二区三区欧美在线| 亚洲日本中文字幕| 久久夜色撩人精品| 久久久最新网址| 国产精品视频不卡| 99精品视频免费全部在线| 欧美另类在线播放| 亚洲视频综合| 欧美在线啊v一区| 亚洲欧洲一区二区在线观看| 日韩亚洲欧美一区| 国产一区二区三区自拍| 亚洲高清一区二区三区| 在线观看亚洲视频啊啊啊啊| 欧美在现视频| 久久一区二区三区av| 久久婷婷国产综合国色天香| 欧美国产日产韩国视频| 欧美福利小视频| 亚洲激情视频在线播放| 欧美大色视频| 亚洲激情精品| 国产亚洲亚洲| 久久精品人人| 亚洲电影第三页| 亚洲美女av黄| 欧美性视频网站| 亚洲欧美日韩国产另类专区| 欧美亚洲视频一区二区| 国内成人精品2018免费看| 亚洲福利精品| 亚洲视频专区在线| 国产精品一二三四区| 亚洲国产精品www| 日韩一级成人av| 欧美无砖砖区免费| 性伦欧美刺激片在线观看| 亚洲日韩欧美视频| 欧美日韩爆操| 欧美电影在线免费观看网站| 亚洲精品日日夜夜| 国产精品久久久久久模特| 午夜欧美大片免费观看| 欧美承认网站| 亚洲永久免费| 欧美日韩一区二区精品| 欧美激情五月| 在线观看日韩一区| 欧美日韩国产成人精品| 亚洲欧美日韩国产| 欧美大片免费| 亚洲欧美日韩精品一区二区| 欧美日韩在线播| 久久高清一区| 99在线热播精品免费99热| 久久久久国内| 国产在线欧美| 欧美日韩日韩| 久久久久国产精品厨房| 一区二区三区毛片| 免费亚洲婷婷| 欧美与黑人午夜性猛交久久久| 亚洲欧洲一区二区三区在线观看 | 欧美一区二区三区精品| 亚洲制服av| 1024成人| 国产一区二区高清视频| 欧美极品在线播放| 99香蕉国产精品偷在线观看| 久久综合九色欧美综合狠狠| 亚洲综合视频一区| 日韩亚洲国产欧美| 精久久久久久| 国产在线精品自拍| 国产精品国产成人国产三级| 午夜精品久久久久久久久久久久久 | 亚洲在线播放电影| 亚洲欧洲日韩在线| 国产中文一区二区三区| 国产精品久久一区二区三区| 欧美日韩国产成人在线| 欧美freesex交免费视频| 亚洲黄一区二区三区| 蜜臀av国产精品久久久久| 久久国产一区| 亚洲日韩欧美视频| 亚洲国产精品久久人人爱蜜臀| 欧美顶级艳妇交换群宴| 久久全国免费视频| 久久国产88| 欧美一区综合| 久久精品一区| 久久精品视频在线观看| 久久精品国产精品亚洲精品| 欧美一区在线视频| 久久国产66| 久久男女视频| 美玉足脚交一区二区三区图片| 久久久99国产精品免费| 久久久久九九视频| 老司机成人网| 国产精品99久久久久久白浆小说 | 亚洲欧洲另类| 亚洲精品中文字幕女同| 久久久91精品国产| 久久久久久9999| 免费观看成人网| 欧美国产日韩一区二区三区| 亚洲电影免费观看高清| 亚洲日本一区二区| 一区二区激情视频| 午夜精品国产| 久久午夜av| 欧美精品一区三区在线观看| 欧美视频1区| 欧美—级a级欧美特级ar全黄| 欧美伦理a级免费电影| 国产精品久久久久久久久免费桃花| 国产精品毛片一区二区三区| 国产一区在线播放| 亚洲人成高清| 午夜精品短视频| 久久综合九色99| 亚洲三级观看| 欧美一二三视频| 欧美成人影音| 国产精品视频网站| 一区在线免费| 亚洲永久网站| 欧美高清在线观看| 亚洲小说春色综合另类电影| 久久久亚洲欧洲日产国码αv| 欧美区高清在线| 国产一区二区三区高清| 亚洲精品视频免费观看| 欧美在线日韩| 亚洲另类视频| 久久婷婷国产麻豆91天堂| 欧美少妇一区| 亚洲国产老妈| 久久青青草原一区二区| 亚洲美女在线看| 久久免费视频在线观看| 国产精品免费看片| 亚洲精品国精品久久99热| 久久久久久久久久久久久久一区| 亚洲精品一区二区三区婷婷月| 久久精品72免费观看| 国产精品国产三级国产aⅴ入口| 亚洲国产免费|