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

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>
            亚洲影院在线观看| 99爱精品视频| 欧美激情久久久久久| 久久一区亚洲| 可以看av的网站久久看| 欧美成人高清视频| 欧美日韩一区二| 国产精品麻豆va在线播放| 欧美亚州韩日在线看免费版国语版| 欧美日韩精选| 欧美激情中文字幕乱码免费| 亚洲欧洲日本专区| 亚洲私人黄色宅男| 久久久精品动漫| 欧美激情综合亚洲一二区| 欧美午夜宅男影院在线观看| 国产女人水真多18毛片18精品视频| 国产一区二区成人久久免费影院| 伊人久久av导航| 亚洲免费在线观看| 免费观看日韩| 一区二区三区四区五区在线| 午夜影院日韩| 欧美人与性动交a欧美精品| 国产精品亚洲片夜色在线| 91久久久久久| 久久www成人_看片免费不卡| 欧美国产成人精品| 亚洲伊人久久综合| 欧美黑人在线观看| 黑人一区二区| 欧美一区二区三区免费视频| 亚洲精品久久久久久久久久久| 香蕉久久久久久久av网站| 欧美好骚综合网| 在线观看欧美| 久久精品一区二区三区中文字幕| 亚洲日本激情| 老司机午夜精品视频| 国产精品一区二区在线观看网站| 亚洲伦理网站| 欧美二区乱c少妇| 久久久久久夜| 韩国福利一区| 久久爱www久久做| 亚洲视频狠狠| 欧美午夜视频网站| 亚洲私人黄色宅男| 亚洲伦理久久| 欧美日韩亚洲国产一区| 亚洲高清不卡在线| 欧美日韩国产大片| 悠悠资源网久久精品| 在线亚洲电影| 91久久在线视频| 欧美国产精品人人做人人爱| 黄色一区二区在线| 久久久久五月天| 亚洲综合成人在线| 国产精品视屏| 欧美亚洲免费在线| 午夜精品视频网站| 国外成人免费视频| 久久人人爽人人爽| 久久久九九九九| 亚洲福利视频在线| 欧美肥婆在线| 欧美电影免费观看高清| 日韩系列欧美系列| 一本色道久久| 国产精品综合不卡av| 久久精品论坛| 久久米奇亚洲| 99ri日韩精品视频| 亚洲一区二区在线看| 国产视频久久久久久久| 久久久一区二区三区| 久久激情五月婷婷| 亚洲黄色精品| 夜夜嗨av一区二区三区| 国产精品日韩在线一区| 久久国产夜色精品鲁鲁99| 久久久久久9999| 亚洲精品在线一区二区| 亚洲素人一区二区| 狠狠做深爱婷婷久久综合一区 | 亚洲欧洲中文日韩久久av乱码| 欧美精品日韩精品| 欧美一区免费视频| 你懂的成人av| 久久av在线看| 免费一级欧美片在线观看| 亚洲一区二区视频在线| 亚洲自拍偷拍视频| 亚洲国产日韩欧美一区二区三区| 亚洲伦理在线| 国产在线视频欧美一区二区三区| 欧美激情日韩| 国产欧美一区二区视频| 亚洲国产日韩欧美在线图片| 国产精品日韩欧美大师| 亚洲国产女人aaa毛片在线| 国产精品入口尤物| 欧美顶级少妇做爰| 国产午夜亚洲精品羞羞网站| 亚洲国产日韩欧美在线99| 99精品国产福利在线观看免费| 亚洲欧洲日本国产| 影音先锋亚洲视频| 亚洲在线1234| 一区二区三区高清不卡| 国产精品一区二区视频| 伊人久久婷婷| 亚洲午夜羞羞片| 久久本道综合色狠狠五月| 亚洲神马久久| 久久美女艺术照精彩视频福利播放| 一区二区高清视频在线观看| 久久嫩草精品久久久久| 欧美在线看片| 国产精品久久久久久久久动漫| 蜜臀99久久精品久久久久久软件| 国产精品嫩草99a| 日韩一级成人av| 亚洲精品国偷自产在线99热| 久久国产精品72免费观看| 欧美一区二区三区在线免费观看 | 欧美亚洲综合另类| 亚洲一区二区av电影| 欧美精品成人一区二区在线观看| 欧美日韩一级黄| 亚洲日本激情| 亚洲免费av片| 欧美国产一区二区在线观看| 欧美成人午夜激情在线| 国产在线高清精品| 欧美亚洲一区二区三区| 欧美在线视频一区| 国产日韩欧美a| 亚洲视频在线观看免费| 欧美高清视频在线| 亚洲精品在线二区| 亚洲欧美国产精品桃花| 国产精品久久久久9999高清| 日韩视频精品| 亚洲在线视频免费观看| 国产精品久久久久久亚洲调教| 在线综合+亚洲+欧美中文字幕| 在线视频亚洲一区| 国产精品久久久91| 欧美中文字幕久久| 欧美成人蜜桃| 国产精品99久久久久久www| 欧美日韩一区三区| 午夜久久tv| 欧美成人精品影院| 亚洲欧洲精品一区二区三区 | 国产一区二区成人| 久久视频一区| 亚洲免费观看在线观看| 久久狠狠久久综合桃花| 亚洲福利专区| 国产精品盗摄久久久| 性色av一区二区怡红| 老妇喷水一区二区三区| 亚洲精品一区二区三| 欧美日韩国产页| 午夜精品在线| 亚洲国产成人av| 西瓜成人精品人成网站| 亚洲国产成人av好男人在线观看| 欧美日韩裸体免费视频| 久久精品国产77777蜜臀| 亚洲国产裸拍裸体视频在线观看乱了中文| 一区二区三区欧美| 日韩一区二区精品葵司在线| 亚洲人成7777| 欧美日韩精品免费观看| 亚洲中字黄色| 女女同性女同一区二区三区91| 亚洲人体大胆视频| 国产精品午夜av在线| 久久亚洲春色中文字幕| 99精品国产福利在线观看免费| 久久国产精品99国产| 亚洲毛片网站| 狠狠色丁香婷婷综合久久片| 欧美日韩不卡在线| 久久国产免费| 亚洲一区二区三区涩| 亚洲国产精品精华液2区45| 久久人人看视频| 欧美在线www| 一本色道久久加勒比88综合| 一区二区亚洲欧洲国产日韩| 国产精品视频导航| 欧美日韩一二三四五区| 欧美h视频在线| 久久亚洲国产精品一区二区| 宅男精品视频|