| 導購 | 订阅 | 在线投稿
分享
 
 
當前位置: 王朝網路 >> c/c++ >> C++中的虛函數(virtual function)(1)
 

C++中的虛函數(virtual function)(1)

2008-06-01 02:06:36  編輯來源:互聯網  简体版  手機版  評論  字體: ||
 
 
  一.簡介

  虛函數是C++中用于實現多態(polymorphism)的機制。核心理念就是通過基類訪問派生類定義的函數。假設我們有下面的類層次:

  class A

  {

  public:

  virtual void foo() { cout << "A::foo() is called" << endl;}

  };

  class B: public A

  {

  public:

  virtual void foo() { cout << "B::foo() is called" << endl;}

  };

  那麽,在使用的時候,我們可以:

  A * a = new B();

  a->foo(); // 在這裏,a雖然是指向A的指針,但是被調用的函數(foo)卻是B的!

  這個例子是虛函數的一個典型應用,通過這個例子,也許你就對虛函數有了一些概念。它虛就虛在所謂「推遲聯編」或者「動態聯編」上,一個類函數的調用並不是在編譯時刻被確定的,而是在運行時刻被確定的。由于編寫代碼的時候並不能確定被調用的是基類的函數還是哪個派生類的函數,所以被成爲「虛」函數。

  虛函數只能借助于指針或者引用來達到多態的效果,假如是下面這樣的代碼,則雖然是虛函數,但它不是多態的:

  class A

  {

  public:

  virtual void foo();

  };

  class B: public A

  {

  virtual void foo();

  };

  void bar()

  {

  A a;

  a.foo(); // A::foo()被調用

  }

  1.1 多態

  在了解了虛函數的意思之後,再考慮什麽是多態就很輕易了。仍然針對上面的類層次,但是使用的方法變的複雜了一些:

  void bar(A * a)

  {

  a->foo(); // 被調用的是A::foo() 還是B::foo()?

  }

  因爲foo()是個虛函數,所以在bar這個函數中,只根據這段代碼,無從確定這裏被調用的是A::foo()還是B::foo(),但是可以肯定的說:假如a指向的是A類的實例,則A::foo()被調用,假如a指向的是B類的實例,則B::foo()被調用。

  這種同一代碼可以産生不同效果的特點,被稱爲「多態」。

  1.2 多態有什麽用?

  多態這麽神奇,但是能用來做什麽呢?這個命題我難以用一兩句話概括,一般的C++教程(或者其它面向對象語言的教程)都用一個畫圖的例子來展示多態的用途,我就不再重複這個例子了,假如你不知道這個例子,隨便找本書應該都有介紹。我試圖從一個抽象的角度描述一下,回頭再結合那個畫圖的例子,也許你就更輕易理解。

  在面向對象的編程中,首先會針對數據進行抽象(確定基類)和繼續(確定派生類),構成類層次。這個類層次的使用者在使用它們的時候,假如仍然在需要基類的時候寫針對基類的代碼,在需要派生類的時候寫針對派生類的代碼,就等于類層次完全暴露在使用者面前。假如這個類層次有任何的改變(增加了新類),都需要使用者「知道」(針對新類寫代碼)。這樣就增加了類層次與其使用者之間的耦合,有人把這種情況列爲程序中的「bad smell」之一。

  多態可以使程序員脫離這種窘境。再回頭看看1.1中的例子,bar()作爲A-B這個類層次的使用者,它並不知道這個類層次中有多少個類,每個類都叫什麽,但是一樣可以很好的工作,當有一個C類從A類派生出來後,bar()也不需要「知道」(修改)。這完全歸功于多態--編譯器針對虛函數産生了可以在運行時刻確定被調用函數的代碼。

  1.3 如何「動態聯編」

  編譯器是如何針對虛函數産生可以再運行時刻確定被調用函數的代碼呢?也就是說,虛函數實際上是如何被編譯器處理的呢?Lippman在深度探索C++對象模型[1]中的不同章節講到了幾種方式,這裏把「標准的」方式簡單介紹一下。

  我所說的「標准」方式,也就是所謂的「VTABLE」機制。編譯器發現一個類中有被聲明爲virtual的函數,就會爲其搞一個虛函數表,也就是VTABLE。VTABLE實際上是一個函數指針的數組,每個虛函數占用這個數組的一個slot。一個類只有一個VTABLE,不管它有多少個實例。派生類有自己的VTABLE,但是派生類的VTABLE與基類的VTABLE有相同的函數排列順序,同名的虛函數被放在兩個數組的相同位置上。在創建類實例的時候,編譯器還會在每個實例的內存布局中增加一個vptr字段,該字段指向本類的VTABLE。通過這些手段,編譯器在看到一個虛函數調用的時候,就會將這個調用改寫,針對1.1中的例子:

  void bar(A * a)

  {

  a->foo();

  }

  會被改寫爲:

  void bar(A * a)

  {

  (a->vptr[1])();

  }

  因爲派生類和基類的foo()函數具有相同的VTABLE索引,而他們的vptr又指向不同的VTABLE,因此通過這樣的方法可以在運行時刻決定調用哪個foo()函數。

  雖然實際情況遠非這麽簡單,但是基本原理大致如此。

  1.4 overload和override

  虛函數總是在派生類中被改寫,這種改寫被稱爲「override」。我經常混淆「overload」和「override」這兩個單詞。但是隨著各類C++的書越來越多,後來的程序員也許不會再犯我犯過的錯誤了。但是我打算澄清一下:

  override是指派生類重寫基類的虛函數,就象我們前面B類中重寫了A類中的foo()函數。重寫的函數必須有一致的參數表和返回值(C++標准答應返回值不同的情況,這個我會在「語法」部分簡單介紹,但是很少編譯器支持這個feature)。這個單詞好象一直沒有什麽合適的中文詞彙來對應,有人譯爲「覆蓋」,還貼切一些。

  overload約定成俗的被翻譯爲「重載」。是指編寫一個與已有函數同名但是參數表不同的函數。例如一個函數即可以接受整型數作爲參數,也可以接受浮點數作爲參數。

  一.簡介

  

  

  虛函數是C++中用于實現多態(polymorphism)的機制。核心理念就是通過基類訪問派生類定義的函數。假設我們有下面的類層次:

  class A

  {

  public:

  virtual void foo() { cout << "A::foo() is called" << endl;}

  };

  class B: public A

  {

  public:

  virtual void foo() { cout << "B::foo() is called" << endl;}

  };

  那麽,在使用的時候,我們可以:

  A * a = new B();

  a->foo(); // 在這裏,a雖然是指向A的指針,但是被調用的函數(foo)卻是B的!

  這個例子是虛函數的一個典型應用,通過這個例子,也許你就對虛函數有了一些概念。它虛就虛在所謂「推遲聯編」或者「動態聯編」上,一個類函數的調用並不是在編譯時刻被確定的,而是在運行時刻被確定的。由于編寫代碼的時候並不能確定被調用的是基類的函數還是哪個派生類的函數,所以被成爲「虛」函數。

  虛函數只能借助于指針或者引用來達到多態的效果,假如是下面這樣的代碼,則雖然是虛函數,但它不是多態的:

  class A

  {

  public:

  virtual void foo();

  };

  class B: public A

  {

  virtual void foo();

  };

  void bar()

  {

  A a;

  a.foo(); // A::foo()被調用

  }

  1.1 多態

  在了解了虛函數的意思之後,再考慮什麽是多態就很輕易了。仍然針對上面的類層次,但是使用的方法變的複雜了一些:

  void bar(A * a)

  {

  a->foo(); // 被調用的是A::foo() 還是B::foo()?

  }

  因爲foo()是個虛函數,所以在bar這個函數中,只根據這段代碼,無從確定這裏被調用的是A::foo()還是B::foo(),但是可以肯定的說:假如a指向的是A類的實例,則A::foo()被調用,假如a指向的是B類的實例,則B::foo()被調用。

  這種同一代碼可以産生不同效果的特點,被稱爲「多態」。

  1.2 多態有什麽用?

  多態這麽神奇,但是能用來做什麽呢?這個命題我難以用一兩句話概括,一般的C++教程(或者其它面向對象語言的教程)都用一個畫圖的例子來展示多態的用途,我就不再重複這個例子了,假如你不知道這個例子,隨便找本書應該都有介紹。我試圖從一個抽象的角度描述一下,回頭再結合那個畫圖的例子,也許你就更輕易理解。

  在面向對象的編程中,首先會針對數據進行抽象(確定基類)和繼續(確定派生類),構成類層次。這個類層次的使用者在使用它們的時候,假如仍然在需要基類的時候寫針對基類的代碼,在需要派生類的時候寫針對派生類的代碼,就等于類層次完全暴露在使用者面前。假如這個類層次有任何的改變(增加了新類),都需要使用者「知道」(針對新類寫代碼)。這樣就增加了類層次與其使用者之間的耦合,有人把這種情況列爲程序中的「bad smell」之一。

  多態可以使程序員脫離這種窘境。再回頭看看1.1中的例子,bar()作爲A-B這個類層次的使用者,它並不知道這個類層次中有多少個類,每個類都叫什麽,但是一樣可以很好的工作,當有一個C類從A類派生出來後,bar()也不需要「知道」(修改)。這完全歸功于多態--編譯器針對虛函數産生了可以在運行時刻確定被調用函數的代碼。

  1.3 如何「動態聯編」

  編譯器是如何針對虛函數産生可以再運行時刻確定被調用函數的代碼呢?也就是說,虛函數實際上是如何被編譯器處理的呢?Lippman在深度探索C++對象模型[1]中的不同章節講到了幾種方式,這裏把「標准的」方式簡單介紹一下。

  我所說的「標准」方式,也就是所謂的「VTABLE」機制。編譯器發現一個類中有被聲明爲virtual的函數,就會爲其搞一個虛函數表,也就是VTABLE。VTABLE實際上是一個函數指針的數組,每個虛函數占用這個數組的一個slot。一個類只有一個VTABLE,不管它有多少個實例。派生類有自己的VTABLE,但是派生類的VTABLE與基類的VTABLE有相同的函數排列順序,同名的虛函數被放在兩個數組的相同位置上。在創建類實例的時候,編譯器還會在每個實例的內存布局中增加一個vptr字段,該字段指向本類的VTABLE。通過這些手段,編譯器在看到一個虛函數調用的時候,就會將這個調用改寫,針對1.1中的例子:

  void bar(A * a)

  {

  a->foo();

  }

  會被改寫爲:

  void bar(A * a)

  {

  (a->vptr[1])();

  }

  因爲派生類和基類的foo()函數具有相同的VTABLE索引,而他們的vptr又指向不同的VTABLE,因此通過這樣的方法可以在運行時刻決定調用哪個foo()函數。

  雖然實際情況遠非這麽簡單,但是基本原理大致如此。

  1.4 overload和override

  虛函數總是在派生類中被改寫,這種改寫被稱爲「override」。我經常混淆「overload」和「override」這兩個單詞。但是隨著各類C++的書越來越多,後來的程序員也許不會再犯我犯過的錯誤了。但是我打算澄清一下:

  override是指派生類重寫基類的虛函數,就象我們前面B類中重寫了A類中的foo()函數。重寫的函數必須有一致的參數表和返回值(C++標准答應返回值不同的情況,這個我會在「語法」部分簡單介紹,但是很少編譯器支持這個feature)。這個單詞好象一直沒有什麽合適的中文詞彙來對應,有人譯爲「覆蓋」,還貼切一些。

  overload約定成俗的被翻譯爲「重載」。是指編寫一個與已有函數同名但是參數表不同的函數。例如一個函數即可以接受整型數作爲參數,也可以接受浮點數作爲參數。 QQread.com 推出遊戲功略 http://www.qqread.com/netgame/game/index.Html 魔獸世界 跑跑卡丁車 街頭籃球 水浒Q傳 龍與地下城OL 征服 軒轅劍5 FIFA07 熱血江湖 大唐風雲 夢幻西遊 武林外傳

  一.簡介

  

  

  虛函數是C++中用于實現多態(polymorphism)的機制。核心理念就是通過基類訪問派生類定義的函數。假設我們有下面的類層次:

  class A

  {

  public:

  virtual void foo() { cout << "A::foo() is called" << endl;}

  };

  class B: public A

  {

  public:

  virtual void foo() { cout << "B::foo() is called" << endl;}

  };

  那麽,在使用的時候,我們可以:

  A * a = new B();

  a->foo(); // 在這裏,a雖然是指向A的指針,但是被調用的函數(foo)卻是B的!

  這個例子是虛函數的一個典型應用,通過這個例子,也許你就對虛函數有了一些概念。它虛就虛在所謂「推遲聯編」或者「動態聯編」上,一個類函數的調用並不是在編譯時刻被確定的,而是在運行時刻被確定的。由于編寫代碼的時候並不能確定被調用的是基類的函數還是哪個派生類的函數,所以被成爲「虛」函數。

  虛函數只能借助于指針或者引用來達到多態的效果,假如是下面這樣的代碼,則雖然是虛函數,但它不是多態的:

  class A

  {

  public:

  virtual void foo();

  };

  class B: public A

  {

  virtual void foo();

  };

  void bar()

  {

  A a;

  a.foo(); // A::foo()被調用

  }

  1.1 多態

  在了解了虛函數的意思之後,再考慮什麽是多態就很輕易了。仍然針對上面的類層次,但是使用的方法變的複雜了一些:

  void bar(A * a)

  {

  a->foo(); // 被調用的是A::foo() 還是B::foo()?

  }

  因爲foo()是個虛函數,所以在bar這個函數中,只根據這段代碼,無從確定這裏被調用的是A::foo()還是B::foo(),但是可以肯定的說:假如a指向的是A類的實例,則A::foo()被調用,假如a指向的是B類的實例,則B::foo()被調用。

  這種同一代碼可以産生不同效果的特點,被稱爲「多態」。

  1.2 多態有什麽用?

  多態這麽神奇,但是能用來做什麽呢?這個命題我難以用一兩句話概括,一般的C++教程(或者其它面向對象語言的教程)都用一個畫圖的例子來展示多態的用途,我就不再重複這個例子了,假如你不知道這個例子,隨便找本書應該都有介紹。我試圖從一個抽象的角度描述一下,回頭再結合那個畫圖的例子,也許你就更輕易理解。

  在面向對象的編程中,首先會針對數據進行抽象(確定基類)和繼續(確定派生類),構成類層次。這個類層次的使用者在使用它們的時候,假如仍然在需要基類的時候寫針對基類的代碼,在需要派生類的時候寫針對派生類的代碼,就等于類層次完全暴露在使用者面前。假如這個類層次有任何的改變(增加了新類),都需要使用者「知道」(針對新類寫代碼)。這樣就增加了類層次與其使用者之間的耦合,有人把這種情況列爲程序中的「bad smell」之一。

  多態可以使程序員脫離這種窘境。再回頭看看1.1中的例子,bar()作爲A-B這個類層次的使用者,它並不知道這個類層次中有多少個類,每個類都叫什麽,但是一樣可以很好的工作,當有一個C類從A類派生出來後,bar()也不需要「知道」(修改)。這完全歸功于多態--編譯器針對虛函數産生了可以在運行時刻確定被調用函數的代碼。

  1.3 如何「動態聯編」

  編譯器是如何針對虛函數産生可以再運行時刻確定被調用函數的代碼呢?也就是說,虛函數實際上是如何被編譯器處理的呢?Lippman在深度探索C++對象模型[1]中的不同章節講到了幾種方式,這裏把「標准的」方式簡單介紹一下。

  我所說的「標准」方式,也就是所謂的「VTABLE」機制。編譯器發現一個類中有被聲明爲virtual的函數,就會爲其搞一個虛函數表,也就是VTABLE。VTABLE實際上是一個函數指針的數組,每個虛函數占用這個數組的一個slot。一個類只有一個VTABLE,不管它有多少個實例。派生類有自己的VTABLE,但是派生類的VTABLE與基類的VTABLE有相同的函數排列順序,同名的虛函數被放在兩個數組的相同位置上。在創建類實例的時候,編譯器還會在每個實例的內存布局中增加一個vptr字段,該字段指向本類的VTABLE。通過這些手段,編譯器在看到一個虛函數調用的時候,就會將這個調用改寫,針對1.1中的例子:

  void bar(A * a)

  {

  a->foo();

  }

  會被改寫爲:

  void bar(A * a)

  {

  (a->vptr[1])();

  }

  因爲派生類和基類的foo()函數具有相同的VTABLE索引,而他們的vptr又指向不同的VTABLE,因此通過這樣的方法可以在運行時刻決定調用哪個foo()函數。

  雖然實際情況遠非這麽簡單,但是基本原理大致如此。

  1.4 overload和override

  虛函數總是在派生類中被改寫,這種改寫被稱爲「override」。我經常混淆「overload」和「override」這兩個單詞。但是隨著各類C++的書越來越多,後來的程序員也許不會再犯我犯過的錯誤了。但是我打算澄清一下:

  override是指派生類重寫基類的虛函數,就象我們前面B類中重寫了A類中的foo()函數。重寫的函數必須有一致的參數表和返回值(C++標准答應返回值不同的情況,這個我會在「語法」部分簡單介紹,但是很少編譯器支持這個feature)。這個單詞好象一直沒有什麽合適的中文詞彙來對應,有人譯爲「覆蓋」,還貼切一些。

  overload約定成俗的被翻譯爲「重載」。是指編寫一個與已有函數同名但是參數表不同的函數。例如一個函數即可以接受整型數作爲參數,也可以接受浮點數作爲參數。 QQread.com 推出遊戲功略 http://www.qqread.com/netgame/game/index.html 魔獸世界 跑跑卡丁車 街頭籃球 水浒Q傳 龍與地下城OL 征服 軒轅劍5 FIFA07 熱血江湖 大唐風雲 夢幻西遊 武林外傳

  一.簡介

  

  

  虛函數是C++中用于實現多態(polymorphism)的機制。核心理念就是通過基類訪問派生類定義的函數。假設我們有下面的類層次:

  class A

  {

  public:

  virtual void foo() { cout << "A::foo() is called" << endl;}

  };

  class B: public A

  {

  public:

  virtual void foo() { cout << "B::foo() is called" << endl;}

  };

  那麽,在使用的時候,我們可以:

  A * a = new B();

  a->foo(); // 在這裏,a雖然是指向A的指針,但是被調用的函數(foo)卻是B的!

  這個例子是虛函數的一個典型應用,通過這個例子,也許你就對虛函數有了一些概念。它虛就虛在所謂「推遲聯編」或者「動態聯編」上,一個類函數的調用並不是在編譯時刻被確定的,而是在運行時刻被確定的。由于編寫代碼的時候並不能確定被調用的是基類的函數還是哪個派生類的函數,所以被成爲「虛」函數。

  虛函數只能借助于指針或者引用來達到多態的效果,假如是下面這樣的代碼,則雖然是虛函數,但它不是多態的:

  class A

  {

  public:

  virtual void foo();

  };

  class B: public A

  {

  virtual void foo();

  };

  void bar()

  {

  A a;

  a.foo(); // A::foo()被調用

  }

  1.1 多態

  在了解了虛函數的意思之後,再考慮什麽是多態就很輕易了。仍然針對上面的類層次,但是使用的方法變的複雜了一些:

  void bar(A * a)

  {

  a->foo(); // 被調用的是A::foo() 還是B::foo()?

  }

  因爲foo()是個虛函數,所以在bar這個函數中,只根據這段代碼,無從確定這裏被調用的是A::foo()還是B::foo(),但是可以肯定的說:假如a指向的是A類的實例,則A::foo()被調用,假如a指向的是B類的實例,則B::foo()被調用。

  這種同一代碼可以産生不同效果的特點,被稱爲「多態」。

  1.2 多態有什麽用?

  多態這麽神奇,但是能用來做什麽呢?這個命題我難以用一兩句話概括,一般的C++教程(或者其它面向對象語言的教程)都用一個畫圖的例子來展示多態的用途,我就不再重複這個例子了,假如你不知道這個例子,隨便找本書應該都有介紹。我試圖從一個抽象的角度描述一下,回頭再結合那個畫圖的例子,也許你就更輕易理解。

  在面向對象的編程中,首先會針對數據進行抽象(確定基類)和繼續(確定派生類),構成類層次。這個類層次的使用者在使用它們的時候,假如仍然在需要基類的時候寫針對基類的代碼,在需要派生類的時候寫針對派生類的代碼,就等于類層次完全暴露在使用者面前。假如這個類層次有任何的改變(增加了新類),都需要使用者「知道」(針對新類寫代碼)。這樣就增加了類層次與其使用者之間的耦合,有人把這種情況列爲程序中的「bad smell」之一。

  多態可以使程序員脫離這種窘境。再回頭看看1.1中的例子,bar()作爲A-B這個類層次的使用者,它並不知道這個類層次中有多少個類,每個類都叫什麽,但是一樣可以很好的工作,當有一個C類從A類派生出來後,bar()也不需要「知道」(修改)。這完全歸功于多態--編譯器針對虛函數産生了可以在運行時刻確定被調用函數的代碼。

  1.3 如何「動態聯編」

  編譯器是如何針對虛函數産生可以再運行時刻確定被調用函數的代碼呢?也就是說,虛函數實際上是如何被編譯器處理的呢?Lippman在深度探索C++對象模型[1]中的不同章節講到了幾種方式,這裏把「標准的」方式簡單介紹一下。

  我所說的「標准」方式,也就是所謂的「VTABLE」機制。編譯器發現一個類中有被聲明爲virtual的函數,就會爲其搞一個虛函數表,也就是VTABLE。VTABLE實際上是一個函數指針的數組,每個虛函數占用這個數組的一個slot。一個類只有一個VTABLE,不管它有多少個實例。派生類有自己的VTABLE,但是派生類的VTABLE與基類的VTABLE有相同的函數排列順序,同名的虛函數被放在兩個數組的相同位置上。在創建類實例的時候,編譯器還會在每個實例的內存布局中增加一個vptr字段,該字段指向本類的VTABLE。通過這些手段,編譯器在看到一個虛函數調用的時候,就會將這個調用改寫,針對1.1中的例子:

  void bar(A * a)

  {

  a->foo();

  }

  會被改寫爲:

  void bar(A * a)

  {

  (a->vptr[1])();

  }

  因爲派生類和基類的foo()函數具有相同的VTABLE索引,而他們的vptr又指向不同的VTABLE,因此通過這樣的方法可以在運行時刻決定調用哪個foo()函數。

  雖然實際情況遠非這麽簡單,但是基本原理大致如此。

  1.4 overload和override

  虛函數總是在派生類中被改寫,這種改寫被稱爲「override」。我經常混淆「overload」和「override」這兩個單詞。但是隨著各類C++的書越來越多,後來的程序員也許不會再犯我犯過的錯誤了。但是我打算澄清一下:

  override是指派生類重寫基類的虛函數,就象我們前面B類中重寫了A類中的foo()函數。重寫的函數必須有一致的參數表和返回值(C++標准答應返回值不同的情況,這個我會在「語法」部分簡單介紹,但是很少編譯器支持這個feature)。這個單詞好象一直沒有什麽合適的中文詞彙來對應,有人譯爲「覆蓋」,還貼切一些。

  overload約定成俗的被翻譯爲「重載」。是指編寫一個與已有函數同名但是參數表不同的函數。例如一個函數即可以接受整型數作爲參數,也可以接受浮點數作爲參數。 QQread.com 推出遊戲功略 http://www.qqread.com/netgame/game/index.html 魔獸世界 跑跑卡丁車 街頭籃球 水浒Q傳 龍與地下城OL 征服 軒轅劍5 FIFA07 熱血江湖 大唐風雲 夢幻西遊 武林外傳

  

   right"(出處:清風軟件下載學院)
 
 
 
上一篇《C++通過WIN32 API獲取邏輯磁盤詳細信息》
下一篇《C程序實現漢字內碼與GB碼》
 
 
 
 
 
 
日版寵物情人插曲《Winding Road》歌詞

日版寵物情人2017的插曲,很帶節奏感,日語的,女生唱的。 最後聽見是在第8集的時候女主手割傷了,然後男主用嘴幫她吸了一下,插曲就出來了。 歌手:Def...

兄弟共妻,我成了他們夜裏的美食

老鍾家的兩個兒子很特別,就是跟其他的人不太一樣,魔一般的執著。兄弟倆都到了要結婚的年齡了,不管自家老爹怎麽磨破嘴皮子,兄弟倆說不娶就不娶,老父母爲兄弟兩操碎了心...

如何磨出破洞牛仔褲?牛仔褲怎麽剪破洞?

把牛仔褲磨出有線的破洞 1、具體工具就是磨腳石,下面墊一個硬物,然後用磨腳石一直磨一直磨,到把那塊磨薄了,用手撕開就好了。出來的洞啊很自然的。需要貓須的話調幾...

我就是掃描下圖得到了敬業福和愛國福

先來看下敬業福和愛國福 今年春節,支付寶再次推出了“五福紅包”活動,表示要“把欠大家的敬業福都還給大家”。 今天該活動正式啓動,和去年一樣,需要收集“五福”...

冰箱異味産生的原因和臭味去除的方法

有時候我們打開冰箱就會聞到一股異味,冰箱裏的這種異味是因爲一些物質發出的氣味的混合體,聞起來讓人惡心。 産生這些異味的主要原因有以下幾點。 1、很多人有這種習...

《極品家丁》1-31集大結局分集劇情介紹

簡介 《極品家丁》講述了現代白領林晚榮無意回到古代金陵,並追隨蕭二小姐化名“林三”進入蕭府,不料卻陰差陽錯上演了一出低級家丁拼搏上位的“林三升職記”。...

李溪芮《極品家丁》片尾曲《你就是我最愛的寶寶》歌詞

你就是我最愛的寶寶 - 李溪芮 (電視劇《極品家丁》片尾曲) 作詞:常馨內 作曲:常馨內 你的眉 又鬼馬的挑 你的嘴 又壞壞的笑 上一秒吵鬧 下...

烏梅的功效與作用以及烏梅的食用禁忌有哪些?

烏梅,又稱春梅,中醫認爲,烏梅味酸,性溫,無毒,具有安心、除熱、下氣、祛痰、止渴調中、殺蟲的功效,治肢體痛、肺痨病。烏梅泡水喝能治傷寒煩熱、止吐瀉,與幹姜一起制...

什麽是脂肪粒?如何消除臉部脂肪粒?

什麽是脂肪粒 在我們的臉上總會長一個個像脂肪的小顆粒,弄也弄不掉,而且顔色還是白白的。它既不是粉刺也不是其他的任何痘痘,它就是脂肪粒。 脂肪粒雖然也是由油脂...

網絡安全治理:國家安全保障的主要方向是打擊犯罪,而不是處置和懲罰受害者

來源:中國青年報 新的攻擊方法不斷湧現,黑客幾乎永遠占據網絡攻擊的上風,我們不可能通過技術手段杜絕網絡攻擊。國家安全保障的主要方向是打擊犯罪,而不是處置和懲罰...

河南夫妻在溫嶺網絡直播“造人”內容涉黃被刑事拘留

夫妻網絡直播“造人”爆紅   1月9日,溫嶺城北派出所接到南京警方的協查通告,他們近期打掉了一個涉黃直播APP平台。而根據掌握的線索,其中有一對涉案的夫妻主播...

如何防止牆紙老化?牆紙變舊變黃怎麽辦?

如何防止牆紙老化? (1)選擇透氣性好的牆紙 市場上牆紙的材質分無紡布的、木纖維的、PVC的、玻璃纖維基材的、布面的等,相對而言,PVC材質的牆紙最不透氣...

鮮肌之謎非日本生産VS鮮肌之謎假日貨是謠言

觀點一:破日本銷售量的“鮮肌之謎” 非日本生産 近一段時間,淘寶上架了一款名爲“鮮肌之謎的” 鲑魚卵巢美容液,號稱是最近日本的一款推出的全新護膚品,産品本身所...

中國最美古詩詞精選摘抄

系腰裙(北宋詞人 張先) 惜霜蟾照夜雲天,朦胧影、畫勾闌。人情縱似長情月,算一年年。又能得、幾番圓。 欲寄西江題葉字,流不到、五亭前。東池始有荷新綠,尚小如...

關于女人的經典語句

關于女人的經典語句1、【做一個獨立的女人】 思想獨立:有主見、有自己的人生觀、價值觀。有上進心,永遠不放棄自己的理想,做一份自己喜愛的事業,擁有快樂和成就...

未來我們可以和性愛機器人結婚嗎?

你想體驗機器人性愛嗎?你想和性愛機器人結婚嗎?如果你想,機器人有拒絕你的權利嗎? 近日,第二屆“國際人類-機器人性愛研討會”大會在倫敦金史密斯大學落下帷幕。而...

全球最變態的十個地方

10.土耳其地下洞穴城市 變態指數:★★☆☆☆ 這是土耳其卡帕多西亞的一個著名景點,傳說是當年基督教徒們爲了躲避戰爭而在此修建。裏面曾住著20000人,...

科學家稱,人類死亡後意識將在另外一個宇宙中繼續存活

據英國《每日快報》報道,一位科學家兼理論家Robert Lanza博士宣稱,世界上並不存在人類死亡,死亡的只是身體。他認爲我們的意識借助我們體內的能量生存,而且...

《屏裏狐》片頭曲《我愛狐狸精》歌詞是什麽?

《我愛狐狸精》 - 劉馨棋   (電視劇《屏裏狐》主題曲)   作詞:金十三&李旦   作曲:劉嘉   狐狸精 狐狸仙   千年修...

 
 
 
一.簡介 虛函數是C++中用于實現多態(polymorphism)的機制。核心理念就是通過基類訪問派生類定義的函數。假設我們有下面的類層次: class A { public: virtual void foo() { cout << "A::foo() is called" << endl;} }; class B: public A { public: virtual void foo() { cout << "B::foo() is called" << endl;} }; 那麽,在使用的時候,我們可以: A * a = new B(); a->foo(); // 在這裏,a雖然是指向A的指針,但是被調用的函數(foo)卻是B的! 這個例子是虛函數的一個典型應用,通過這個例子,也許你就對虛函數有了一些概念。它虛就虛在所謂「推遲聯編」或者「動態聯編」上,一個類函數的調用並不是在編譯時刻被確定的,而是在運行時刻被確定的。由于編寫代碼的時候並不能確定被調用的是基類的函數還是哪個派生類的函數,所以被成爲「虛」函數。 虛函數只能借助于指針或者引用來達到多態的效果,假如是下面這樣的代碼,則雖然是虛函數,但它不是多態的: class A { public: virtual void foo(); }; class B: public A { virtual void foo(); }; void bar() { A a; a.foo(); // A::foo()被調用 } 1.1 多態 在了解了虛函數的意思之後,再考慮什麽是多態就很輕易了。仍然針對上面的類層次,但是使用的方法變的複雜了一些: void bar(A * a) { a->foo(); // 被調用的是A::foo() 還是B::foo()? } 因爲foo()是個虛函數,所以在bar這個函數中,只根據這段代碼,無從確定這裏被調用的是A::foo()還是B::foo(),但是可以肯定的說:假如a指向的是A類的實例,則A::foo()被調用,假如a指向的是B類的實例,則B::foo()被調用。 這種同一代碼可以産生不同效果的特點,被稱爲「多態」。 1.2 多態有什麽用? 多態這麽神奇,但是能用來做什麽呢?這個命題我難以用一兩句話概括,一般的C++教程(或者其它面向對象語言的教程)都用一個畫圖的例子來展示多態的用途,我就不再重複這個例子了,假如你不知道這個例子,隨便找本書應該都有介紹。我試圖從一個抽象的角度描述一下,回頭再結合那個畫圖的例子,也許你就更輕易理解。 在面向對象的編程中,首先會針對數據進行抽象(確定基類)和繼續(確定派生類),構成類層次。這個類層次的使用者在使用它們的時候,假如仍然在需要基類的時候寫針對基類的代碼,在需要派生類的時候寫針對派生類的代碼,就等于類層次完全暴露在使用者面前。假如這個類層次有任何的改變(增加了新類),都需要使用者「知道」(針對新類寫代碼)。這樣就增加了類層次與其使用者之間的耦合,有人把這種情況列爲程序中的「bad smell」之一。 多態可以使程序員脫離這種窘境。再回頭看看1.1中的例子,bar()作爲A-B這個類層次的使用者,它並不知道這個類層次中有多少個類,每個類都叫什麽,但是一樣可以很好的工作,當有一個C類從A類派生出來後,bar()也不需要「知道」(修改)。這完全歸功于多態--編譯器針對虛函數産生了可以在運行時刻確定被調用函數的代碼。 1.3 如何「動態聯編」 編譯器是如何針對虛函數産生可以再運行時刻確定被調用函數的代碼呢?也就是說,虛函數實際上是如何被編譯器處理的呢?Lippman在深度探索C++對象模型[1]中的不同章節講到了幾種方式,這裏把「標准的」方式簡單介紹一下。 我所說的「標准」方式,也就是所謂的「VTABLE」機制。編譯器發現一個類中有被聲明爲virtual的函數,就會爲其搞一個虛函數表,也就是VTABLE。VTABLE實際上是一個函數指針的數組,每個虛函數占用這個數組的一個slot。一個類只有一個VTABLE,不管它有多少個實例。派生類有自己的VTABLE,但是派生類的VTABLE與基類的VTABLE有相同的函數排列順序,同名的虛函數被放在兩個數組的相同位置上。在創建類實例的時候,編譯器還會在每個實例的內存布局中增加一個vptr字段,該字段指向本類的VTABLE。通過這些手段,編譯器在看到一個虛函數調用的時候,就會將這個調用改寫,針對1.1中的例子: void bar(A * a) { a->foo(); } 會被改寫爲: void bar(A * a) { (a->vptr[1])(); } 因爲派生類和基類的foo()函數具有相同的VTABLE索引,而他們的vptr又指向不同的VTABLE,因此通過這樣的方法可以在運行時刻決定調用哪個foo()函數。 雖然實際情況遠非這麽簡單,但是基本原理大致如此。 1.4 overload和override 虛函數總是在派生類中被改寫,這種改寫被稱爲「override」。我經常混淆「overload」和「override」這兩個單詞。但是隨著各類C++的書越來越多,後來的程序員也許不會再犯我犯過的錯誤了。但是我打算澄清一下: override是指派生類重寫基類的虛函數,就象我們前面B類中重寫了A類中的foo()函數。重寫的函數必須有一致的參數表和返回值(C++標准答應返回值不同的情況,這個我會在「語法」部分簡單介紹,但是很少編譯器支持這個feature)。這個單詞好象一直沒有什麽合適的中文詞彙來對應,有人譯爲「覆蓋」,還貼切一些。 overload約定成俗的被翻譯爲「重載」。是指編寫一個與已有函數同名但是參數表不同的函數。例如一個函數即可以接受整型數作爲參數,也可以接受浮點數作爲參數。 一.簡介 虛函數是C++中用于實現多態(polymorphism)的機制。核心理念就是通過基類訪問派生類定義的函數。假設我們有下面的類層次: class A { public: virtual void foo() { cout << "A::foo() is called" << endl;} }; class B: public A { public: virtual void foo() { cout << "B::foo() is called" << endl;} }; 那麽,在使用的時候,我們可以: A * a = new B(); a->foo(); // 在這裏,a雖然是指向A的指針,但是被調用的函數(foo)卻是B的! 這個例子是虛函數的一個典型應用,通過這個例子,也許你就對虛函數有了一些概念。它虛就虛在所謂「推遲聯編」或者「動態聯編」上,一個類函數的調用並不是在編譯時刻被確定的,而是在運行時刻被確定的。由于編寫代碼的時候並不能確定被調用的是基類的函數還是哪個派生類的函數,所以被成爲「虛」函數。 虛函數只能借助于指針或者引用來達到多態的效果,假如是下面這樣的代碼,則雖然是虛函數,但它不是多態的: class A { public: virtual void foo(); }; class B: public A { virtual void foo(); }; void bar() { A a; a.foo(); // A::foo()被調用 } 1.1 多態 在了解了虛函數的意思之後,再考慮什麽是多態就很輕易了。仍然針對上面的類層次,但是使用的方法變的複雜了一些: void bar(A * a) { a->foo(); // 被調用的是A::foo() 還是B::foo()? } 因爲foo()是個虛函數,所以在bar這個函數中,只根據這段代碼,無從確定這裏被調用的是A::foo()還是B::foo(),但是可以肯定的說:假如a指向的是A類的實例,則A::foo()被調用,假如a指向的是B類的實例,則B::foo()被調用。 這種同一代碼可以産生不同效果的特點,被稱爲「多態」。 1.2 多態有什麽用? 多態這麽神奇,但是能用來做什麽呢?這個命題我難以用一兩句話概括,一般的C++教程(或者其它面向對象語言的教程)都用一個畫圖的例子來展示多態的用途,我就不再重複這個例子了,假如你不知道這個例子,隨便找本書應該都有介紹。我試圖從一個抽象的角度描述一下,回頭再結合那個畫圖的例子,也許你就更輕易理解。 在面向對象的編程中,首先會針對數據進行抽象(確定基類)和繼續(確定派生類),構成類層次。這個類層次的使用者在使用它們的時候,假如仍然在需要基類的時候寫針對基類的代碼,在需要派生類的時候寫針對派生類的代碼,就等于類層次完全暴露在使用者面前。假如這個類層次有任何的改變(增加了新類),都需要使用者「知道」(針對新類寫代碼)。這樣就增加了類層次與其使用者之間的耦合,有人把這種情況列爲程序中的「bad smell」之一。 多態可以使程序員脫離這種窘境。再回頭看看1.1中的例子,bar()作爲A-B這個類層次的使用者,它並不知道這個類層次中有多少個類,每個類都叫什麽,但是一樣可以很好的工作,當有一個C類從A類派生出來後,bar()也不需要「知道」(修改)。這完全歸功于多態--編譯器針對虛函數産生了可以在運行時刻確定被調用函數的代碼。 1.3 如何「動態聯編」 編譯器是如何針對虛函數産生可以再運行時刻確定被調用函數的代碼呢?也就是說,虛函數實際上是如何被編譯器處理的呢?Lippman在深度探索C++對象模型[1]中的不同章節講到了幾種方式,這裏把「標准的」方式簡單介紹一下。 我所說的「標准」方式,也就是所謂的「VTABLE」機制。編譯器發現一個類中有被聲明爲virtual的函數,就會爲其搞一個虛函數表,也就是VTABLE。VTABLE實際上是一個函數指針的數組,每個虛函數占用這個數組的一個slot。一個類只有一個VTABLE,不管它有多少個實例。派生類有自己的VTABLE,但是派生類的VTABLE與基類的VTABLE有相同的函數排列順序,同名的虛函數被放在兩個數組的相同位置上。在創建類實例的時候,編譯器還會在每個實例的內存布局中增加一個vptr字段,該字段指向本類的VTABLE。通過這些手段,編譯器在看到一個虛函數調用的時候,就會將這個調用改寫,針對1.1中的例子: void bar(A * a) { a->foo(); } 會被改寫爲: void bar(A * a) { (a->vptr[1])(); } 因爲派生類和基類的foo()函數具有相同的VTABLE索引,而他們的vptr又指向不同的VTABLE,因此通過這樣的方法可以在運行時刻決定調用哪個foo()函數。 雖然實際情況遠非這麽簡單,但是基本原理大致如此。 1.4 overload和override 虛函數總是在派生類中被改寫,這種改寫被稱爲「override」。我經常混淆「overload」和「override」這兩個單詞。但是隨著各類C++的書越來越多,後來的程序員也許不會再犯我犯過的錯誤了。但是我打算澄清一下: override是指派生類重寫基類的虛函數,就象我們前面B類中重寫了A類中的foo()函數。重寫的函數必須有一致的參數表和返回值(C++標准答應返回值不同的情況,這個我會在「語法」部分簡單介紹,但是很少編譯器支持這個feature)。這個單詞好象一直沒有什麽合適的中文詞彙來對應,有人譯爲「覆蓋」,還貼切一些。 overload約定成俗的被翻譯爲「重載」。是指編寫一個與已有函數同名但是參數表不同的函數。例如一個函數即可以接受整型數作爲參數,也可以接受浮點數作爲參數。 QQread.com 推出遊戲功略 http://www.qqread.com/netgame/game/index.Html 魔獸世界 跑跑卡丁車 街頭籃球 水浒Q傳 龍與地下城OL 征服 軒轅劍5 FIFA07 熱血江湖 大唐風雲 夢幻西遊 武林外傳 一.簡介 虛函數是C++中用于實現多態(polymorphism)的機制。核心理念就是通過基類訪問派生類定義的函數。假設我們有下面的類層次: class A { public: virtual void foo() { cout << "A::foo() is called" << endl;} }; class B: public A { public: virtual void foo() { cout << "B::foo() is called" << endl;} }; 那麽,在使用的時候,我們可以: A * a = new B(); a->foo(); // 在這裏,a雖然是指向A的指針,但是被調用的函數(foo)卻是B的! 這個例子是虛函數的一個典型應用,通過這個例子,也許你就對虛函數有了一些概念。它虛就虛在所謂「推遲聯編」或者「動態聯編」上,一個類函數的調用並不是在編譯時刻被確定的,而是在運行時刻被確定的。由于編寫代碼的時候並不能確定被調用的是基類的函數還是哪個派生類的函數,所以被成爲「虛」函數。 虛函數只能借助于指針或者引用來達到多態的效果,假如是下面這樣的代碼,則雖然是虛函數,但它不是多態的: class A { public: virtual void foo(); }; class B: public A { virtual void foo(); }; void bar() { A a; a.foo(); // A::foo()被調用 } 1.1 多態 在了解了虛函數的意思之後,再考慮什麽是多態就很輕易了。仍然針對上面的類層次,但是使用的方法變的複雜了一些: void bar(A * a) { a->foo(); // 被調用的是A::foo() 還是B::foo()? } 因爲foo()是個虛函數,所以在bar這個函數中,只根據這段代碼,無從確定這裏被調用的是A::foo()還是B::foo(),但是可以肯定的說:假如a指向的是A類的實例,則A::foo()被調用,假如a指向的是B類的實例,則B::foo()被調用。 這種同一代碼可以産生不同效果的特點,被稱爲「多態」。 1.2 多態有什麽用? 多態這麽神奇,但是能用來做什麽呢?這個命題我難以用一兩句話概括,一般的C++教程(或者其它面向對象語言的教程)都用一個畫圖的例子來展示多態的用途,我就不再重複這個例子了,假如你不知道這個例子,隨便找本書應該都有介紹。我試圖從一個抽象的角度描述一下,回頭再結合那個畫圖的例子,也許你就更輕易理解。 在面向對象的編程中,首先會針對數據進行抽象(確定基類)和繼續(確定派生類),構成類層次。這個類層次的使用者在使用它們的時候,假如仍然在需要基類的時候寫針對基類的代碼,在需要派生類的時候寫針對派生類的代碼,就等于類層次完全暴露在使用者面前。假如這個類層次有任何的改變(增加了新類),都需要使用者「知道」(針對新類寫代碼)。這樣就增加了類層次與其使用者之間的耦合,有人把這種情況列爲程序中的「bad smell」之一。 多態可以使程序員脫離這種窘境。再回頭看看1.1中的例子,bar()作爲A-B這個類層次的使用者,它並不知道這個類層次中有多少個類,每個類都叫什麽,但是一樣可以很好的工作,當有一個C類從A類派生出來後,bar()也不需要「知道」(修改)。這完全歸功于多態--編譯器針對虛函數産生了可以在運行時刻確定被調用函數的代碼。 1.3 如何「動態聯編」 編譯器是如何針對虛函數産生可以再運行時刻確定被調用函數的代碼呢?也就是說,虛函數實際上是如何被編譯器處理的呢?Lippman在深度探索C++對象模型[1]中的不同章節講到了幾種方式,這裏把「標准的」方式簡單介紹一下。 我所說的「標准」方式,也就是所謂的「VTABLE」機制。編譯器發現一個類中有被聲明爲virtual的函數,就會爲其搞一個虛函數表,也就是VTABLE。VTABLE實際上是一個函數指針的數組,每個虛函數占用這個數組的一個slot。一個類只有一個VTABLE,不管它有多少個實例。派生類有自己的VTABLE,但是派生類的VTABLE與基類的VTABLE有相同的函數排列順序,同名的虛函數被放在兩個數組的相同位置上。在創建類實例的時候,編譯器還會在每個實例的內存布局中增加一個vptr字段,該字段指向本類的VTABLE。通過這些手段,編譯器在看到一個虛函數調用的時候,就會將這個調用改寫,針對1.1中的例子: void bar(A * a) { a->foo(); } 會被改寫爲: void bar(A * a) { (a->vptr[1])(); } 因爲派生類和基類的foo()函數具有相同的VTABLE索引,而他們的vptr又指向不同的VTABLE,因此通過這樣的方法可以在運行時刻決定調用哪個foo()函數。 雖然實際情況遠非這麽簡單,但是基本原理大致如此。 1.4 overload和override 虛函數總是在派生類中被改寫,這種改寫被稱爲「override」。我經常混淆「overload」和「override」這兩個單詞。但是隨著各類C++的書越來越多,後來的程序員也許不會再犯我犯過的錯誤了。但是我打算澄清一下: override是指派生類重寫基類的虛函數,就象我們前面B類中重寫了A類中的foo()函數。重寫的函數必須有一致的參數表和返回值(C++標准答應返回值不同的情況,這個我會在「語法」部分簡單介紹,但是很少編譯器支持這個feature)。這個單詞好象一直沒有什麽合適的中文詞彙來對應,有人譯爲「覆蓋」,還貼切一些。 overload約定成俗的被翻譯爲「重載」。是指編寫一個與已有函數同名但是參數表不同的函數。例如一個函數即可以接受整型數作爲參數,也可以接受浮點數作爲參數。 QQread.com 推出遊戲功略 http://www.qqread.com/netgame/game/index.html 魔獸世界 跑跑卡丁車 街頭籃球 水浒Q傳 龍與地下城OL 征服 軒轅劍5 FIFA07 熱血江湖 大唐風雲 夢幻西遊 武林外傳 一.簡介 虛函數是C++中用于實現多態(polymorphism)的機制。核心理念就是通過基類訪問派生類定義的函數。假設我們有下面的類層次: class A { public: virtual void foo() { cout << "A::foo() is called" << endl;} }; class B: public A { public: virtual void foo() { cout << "B::foo() is called" << endl;} }; 那麽,在使用的時候,我們可以: A * a = new B(); a->foo(); // 在這裏,a雖然是指向A的指針,但是被調用的函數(foo)卻是B的! 這個例子是虛函數的一個典型應用,通過這個例子,也許你就對虛函數有了一些概念。它虛就虛在所謂「推遲聯編」或者「動態聯編」上,一個類函數的調用並不是在編譯時刻被確定的,而是在運行時刻被確定的。由于編寫代碼的時候並不能確定被調用的是基類的函數還是哪個派生類的函數,所以被成爲「虛」函數。 虛函數只能借助于指針或者引用來達到多態的效果,假如是下面這樣的代碼,則雖然是虛函數,但它不是多態的: class A { public: virtual void foo(); }; class B: public A { virtual void foo(); }; void bar() { A a; a.foo(); // A::foo()被調用 } 1.1 多態 在了解了虛函數的意思之後,再考慮什麽是多態就很輕易了。仍然針對上面的類層次,但是使用的方法變的複雜了一些: void bar(A * a) { a->foo(); // 被調用的是A::foo() 還是B::foo()? } 因爲foo()是個虛函數,所以在bar這個函數中,只根據這段代碼,無從確定這裏被調用的是A::foo()還是B::foo(),但是可以肯定的說:假如a指向的是A類的實例,則A::foo()被調用,假如a指向的是B類的實例,則B::foo()被調用。 這種同一代碼可以産生不同效果的特點,被稱爲「多態」。 1.2 多態有什麽用? 多態這麽神奇,但是能用來做什麽呢?這個命題我難以用一兩句話概括,一般的C++教程(或者其它面向對象語言的教程)都用一個畫圖的例子來展示多態的用途,我就不再重複這個例子了,假如你不知道這個例子,隨便找本書應該都有介紹。我試圖從一個抽象的角度描述一下,回頭再結合那個畫圖的例子,也許你就更輕易理解。 在面向對象的編程中,首先會針對數據進行抽象(確定基類)和繼續(確定派生類),構成類層次。這個類層次的使用者在使用它們的時候,假如仍然在需要基類的時候寫針對基類的代碼,在需要派生類的時候寫針對派生類的代碼,就等于類層次完全暴露在使用者面前。假如這個類層次有任何的改變(增加了新類),都需要使用者「知道」(針對新類寫代碼)。這樣就增加了類層次與其使用者之間的耦合,有人把這種情況列爲程序中的「bad smell」之一。 多態可以使程序員脫離這種窘境。再回頭看看1.1中的例子,bar()作爲A-B這個類層次的使用者,它並不知道這個類層次中有多少個類,每個類都叫什麽,但是一樣可以很好的工作,當有一個C類從A類派生出來後,bar()也不需要「知道」(修改)。這完全歸功于多態--編譯器針對虛函數産生了可以在運行時刻確定被調用函數的代碼。 1.3 如何「動態聯編」 編譯器是如何針對虛函數産生可以再運行時刻確定被調用函數的代碼呢?也就是說,虛函數實際上是如何被編譯器處理的呢?Lippman在深度探索C++對象模型[1]中的不同章節講到了幾種方式,這裏把「標准的」方式簡單介紹一下。 我所說的「標准」方式,也就是所謂的「VTABLE」機制。編譯器發現一個類中有被聲明爲virtual的函數,就會爲其搞一個虛函數表,也就是VTABLE。VTABLE實際上是一個函數指針的數組,每個虛函數占用這個數組的一個slot。一個類只有一個VTABLE,不管它有多少個實例。派生類有自己的VTABLE,但是派生類的VTABLE與基類的VTABLE有相同的函數排列順序,同名的虛函數被放在兩個數組的相同位置上。在創建類實例的時候,編譯器還會在每個實例的內存布局中增加一個vptr字段,該字段指向本類的VTABLE。通過這些手段,編譯器在看到一個虛函數調用的時候,就會將這個調用改寫,針對1.1中的例子: void bar(A * a) { a->foo(); } 會被改寫爲: void bar(A * a) { (a->vptr[1])(); } 因爲派生類和基類的foo()函數具有相同的VTABLE索引,而他們的vptr又指向不同的VTABLE,因此通過這樣的方法可以在運行時刻決定調用哪個foo()函數。 雖然實際情況遠非這麽簡單,但是基本原理大致如此。 1.4 overload和override 虛函數總是在派生類中被改寫,這種改寫被稱爲「override」。我經常混淆「overload」和「override」這兩個單詞。但是隨著各類C++的書越來越多,後來的程序員也許不會再犯我犯過的錯誤了。但是我打算澄清一下: override是指派生類重寫基類的虛函數,就象我們前面B類中重寫了A類中的foo()函數。重寫的函數必須有一致的參數表和返回值(C++標准答應返回值不同的情況,這個我會在「語法」部分簡單介紹,但是很少編譯器支持這個feature)。這個單詞好象一直沒有什麽合適的中文詞彙來對應,有人譯爲「覆蓋」,還貼切一些。 overload約定成俗的被翻譯爲「重載」。是指編寫一個與已有函數同名但是參數表不同的函數。例如一個函數即可以接受整型數作爲參數,也可以接受浮點數作爲參數。 QQread.com 推出遊戲功略 http://www.qqread.com/netgame/game/index.html 魔獸世界 跑跑卡丁車 街頭籃球 水浒Q傳 龍與地下城OL 征服 軒轅劍5 FIFA07 熱血江湖 大唐風雲 夢幻西遊 武林外傳 right"(出處:清風軟件下載學院)
󰈣󰈤
 
 
 
  免責聲明:本文僅代表作者個人觀點,與王朝網路無關。王朝網路登載此文出於傳遞更多信息之目的,並不意味著贊同其觀點或證實其描述,其原創性以及文中陳述文字和內容未經本站證實,對本文以及其中全部或者部分內容、文字的真實性、完整性、及時性本站不作任何保證或承諾,請讀者僅作參考,並請自行核實相關內容。
 
 
陽光靓麗的模特兒(8)
陽光靓麗的模特兒(7)
陽光靓麗的模特兒(6)
陽光靓麗的模特兒(5)
秋-印象
德慶盤龍峽 一
松江印象之三
雲之南(寬幅)
 
>>返回首頁<<
 
 
 
 熱帖排行
 
 
 
 
© 2005- 王朝網路 版權所有