1. 程式人生 > >(C++)C++多型性中的靜態繫結和動態繫結

(C++)C++多型性中的靜態繫結和動態繫結

靜態繫結和動態繫結是C++多型性的一種特性。

1、物件的靜態型別和動態型別:

  • 物件的靜態型別:

物件在宣告是採用的型別,在編譯期確定;

  • 物件的動態型別:

當前物件所指的型別,在執行期決定,物件的動態型別可以更改,但靜態型別無法更改。

class B{

};

class C: public B{

};

class D: public B{

};

D* pD=new D();
// pD的靜態型別是它宣告的型別D*,動態型別也是D*
B* pB=pD;
// pB的靜態型別是它宣告的型別B*,動態型別是pB所指的物件pD的型別D*
c* pC=new C();
// pC的靜態型別是它宣告的型別C*,動態型別也是C*
pB=pC;
// pB的動態型別可以改變,現在它的動態型別為C*

2、靜態繫結和動態繫結

  • 靜態繫結:

繫結的是物件的靜態型別,某特性(比如函式)依賴於物件的靜態型別,發生在編譯期。

  • 動態繫結:

繫結的是物件的動態型別,某特性(比如函式)依賴於物件的動態型別,發生在執行期。

class B{
    void DoSomething();
    virtual void vfun();
};

class C: public B{
    //首先說明一下,這個子類重新定義了父類的no-virtual函式,這是一個不好的設計,會導致名稱遮掩;這裡只是為了說明動態繫結和靜態繫結才這樣使用。  
    void DoSomething();
    virtual void vfun();
};

class D: public B{
    void DoSomething();
    virtual void vfun();
};

D* pD=new D();
// pD的靜態型別是它宣告的型別D*,動態型別也是D*
B* pB=pD;
// pB的靜態型別是它宣告的型別B*,動態型別是pB所指的物件pD的型別D*

pD->DoSomething()和pB->DoSomething()呼叫的是同一個函式嗎?

答案:不是的,雖然pD和pB指向同一物件,但函式DoSomething是一個non-virtual函式,它是靜態繫結的,也就是編譯器會在編譯器根據物件的靜態型別來選擇函式,pD的靜態型別是D*,那麼編譯器在處理pD->DoSomething()的時候會將它指向D::DoSomething()。同理,pB的靜態型別是B*,那麼pB->DoSomething()呼叫的就是B::DosSomething()。

pD->vfun()和pB->vfun()呼叫的是同一函式嗎?

答案:是的,vfun是個虛擬函式,它是動態繫結的,也就是它繫結的是物件的動態型別,pB和pD雖然靜態型別不同,但他們同時指向一個物件,他們的動態物件是相同的,都是D*,所以,他們呼叫的是同一個函式:D::vfun()。

上面都是針對物件指標的情況,對於引用(reference)的情況同樣適用。

指標和引用的動態型別和靜態型別可能會不一致,但是物件的動態型別和靜態型別是一致的。
D D;
D.DoSomething()和D.vfun()永遠呼叫的都是D::DoSomething()和D::vfun()。

總結:只有虛擬函式才使用的是動態繫結,其他的全部是靜態繫結。

當預設引數和虛擬函式一起出現的時候情況有點複雜,極易出錯。我們知道,虛擬函式是動態繫結的,但是為了執行效率,預設引數是靜態繫結的

class B{
    void DoSomething();
    virtual void vfun(int i=10);
};


class D: public B{
    void DoSomething();
    virtual void vfun(int i=20);
};

D* pD=new D();
// pD的靜態型別是它宣告的型別D*,動態型別也是D*
B* pB=pD;
// pB的靜態型別是它宣告的型別B*,動態型別是pB所指的物件pD的型別D*
pD->vfun();
pB->vfun();

有上面的分析可知,pD->vfun()和pB->vfun()呼叫都是函式D::vfun(),但是他們的預設引數是多少?

分析一下,預設引數是靜態繫結的,pD->vfun(),pD的靜態型別是D*,所以它的預設引數是20;而pB的靜態型別是B*,所以pB->vfun()的預設引數是10.

對於這個特性,估計沒有人會喜歡。所以,永遠記住:
“絕不重新定義繼承而來的預設引數(Never redefine function’s inherited default parameters value.)”

參考文章:

http://blog.csdn.net/chgaowei/article/details/6427731

相關推薦

C++C++靜態動態

靜態繫結和動態繫結是C++多型性的一種特性。 1、物件的靜態型別和動態型別: 物件的靜態型別: 物件在宣告是採用的型別,在編譯期確定; 物件的動態型別: 當前物件所指的型別,在執行期決定,物件的動態型別可以更改,但靜態型別無法更改。 class B{ }; clas

c/c++ 繼承與 繼承的public, protected, private

問題:類B私有繼承類A,類A有個protected成員,那麼在類B的成員函式裡是否可以使用類A的protected成員? 可以使用。 估計有的同學說不對吧,類B都私有繼承了類A了,怎麼還能訪問類A的protect成員呢?請看下面的例子。在類Pri_derv的f()成員函式裡是可以方位父類Base的pub_

【python】Python + C/C++ 嵌入式程式設計1維陣列Numpy.Array()在PythonC/C++檔案間的傳遞問題

Python 提供了豐富的 C API 函式,我們使用這些 C API 函式可以實現將 Python 檔案中的函式、類等在 C/C++ 檔案中進行呼叫,從而使得我們可以方便地使用 Python 程式碼來幫助我們實現一些額外的需求(如:嵌入神經網路模型)。 網上已經有很多

通過程式設計幾何圖形Shape、矩形Rectangle、圓形Circle、正方形Square幾種型別, 能夠利用介面計算幾何圖形的面積周長並顯示。

interface Shape {//宣告介面Shapefinal float PI = 3.14f; // 定義常量圓周率abstract void area();//定義抽象方法面積abstract void perimeter();//定義抽象方法周長}clas

ASP.NET Core 中文文件 第三章 原理11個環境工作

ASP.NET Core 介紹了支援在多個環境中管理應用程式行為的改進,如開發(development),預演(staging)和生產(production)。環境變數用來指示應用程式正在執行的環境,允許應用程式適當地配置。 章節: 開發,預演,生產 ASP.NET Core 引用了一個特定的環境變數

C++靜態動態

(感謝原作者分享:http://www.cnblogs.com/lizhenghn/p/3657717.html) C++在面向物件程式設計中,存在著靜態繫結和動態繫結的定義,本節即是主要講述這兩點區分。 我是在一個類的繼承體系中分析的,因此下面所說的物件一般就是指一個類的例項。 首先我們需要明確幾個名詞定

js過濾去除富文字編輯器的html標籤換行回車等標記的正則表示式

一段這樣的Html包裹的文字: var description="<p>\n\t<img src=\"http://localhost/Scripts/KindEditor/Editor/plugins/emoticons/images/0.gif\" a

前端框架DIV選複選框框的封裝MySql資料庫存取

         圖可以包含的寓意和含義是文字不能比擬的,先有一個效果圖你也就知道這篇文章的主要內容是關於什麼問題的,省去了一大堆文字的累述,看下面這張圖:                    這個需求就是要實現某個人具有另外一種特性,具有多對多關係,比如某個人既喜歡運

機器學習筆記6——C4.5決策樹的剪枝處理Python實現

1. 為什麼要剪枝 還記得決策樹的構造過程嗎?為了儘可能正確分類訓練樣本,節點的劃分過程會不斷重複直到不能再分,這樣就可能對訓練樣本學習的“太好”了,把訓練樣本的一些特點當做所有資料都具有的一般性質,cong從而導致過擬合。這時就可以通過剪枝處理去掉yi一些分支來降低過擬合

利用介面計算幾何圖形的面積周長並顯示

public interface Shape {       public double area();               //計算面積       public double perimeter();              //計算周長   }       

Spring AOP 前篇:Java代理之JDK靜態代理、JDK動態代理、CGLIB動態代理

Spring AOP 前篇:Java代理之JDK靜態代理、JDK動態代理、CGLIB動態代理 該文章參考多篇文章的基礎上進行了簡化並做少許修改,方便理解。原文章地址如下: Java之代理(jdk靜態代理,jdk動態代理,cglib動態代理,aop,aspectj

Java靜態變量動態變量

.com pan 1-1 一道 args ict print stat 類的加載 這是我面試遇到的一道題,題目如下: 1 public class StaticTest { 2 private static int b = 1; 3 priv

詳解C++的純虛擬函式虛擬函式區別& 以及理解

#include <iostream> #include <cstdio> using namespace std; class A { public:     void foo()     {         printf("1\n");    

C++ 第六章虛擬函式上篇

目錄 多型性 多型性的定義 例子 虛擬函式 虛擬函式的作用 什麼情況下使用虛擬函式 虛解構函式 純虛擬函式和抽象類 什麼是多型性 面對不同的物件傳送同一個訊息,不同的物件

C++ 第六章虛擬函式下篇虛解構函式純虛擬函式

一,虛解構函式 如果用new運算子建立了臨時物件,若基類中有解構函式並且定義了一個指向該基類的指標變數。在程式用帶指標引數的delete運算子撤銷物件時,會發生:系統只執行基類的解構函式,而不執行派生類的解構函式。 #include<iostream> using

C++程式設計—— 虛擬函式

一、多型性         靜態聯編所支援的多型性稱為編譯時的多型性,當呼叫過載函式時,編譯器可以根據呼叫時所使用的實參在編譯時就確定應該呼叫哪個函式;動態聯編所支援的多型性稱為執行時的多型性,這由虛擬函式來支援。虛擬函式類似於過載函式,但與過載函式的實現策略不同,即對虛擬

C++類物件虛擬函式與的實現

在面向物件程式設計時,有時會遇到這種需求:我們希望同一個方法在基類和派生類中實現不同的功能,即體現出行為上的多型性。一般有兩種方法可以實現這種需求,其一是在派生類中重新定義基類中方法,其二是使用虛擬函式。這裡主要記錄利用虛擬函式實現多型性的方法。 類中虛擬函式的定義方法 虛擬函式

Java之物件的使用生活通俗的例子講解

Java之物件的多型性多型概念 (Java)    多型(英語:polymorphism),是指計算機程式執行時,相同的訊息可能會送給多個不同的類別之物件,而系統可依據物件所屬類別,引發對應類別的方法,而有不同的行為。簡單來說,所謂多型意指相同的訊息給予不同的物件會引發不同的

C#.架構設計 資料c# 專案包含了個模組或個功能,如何靈活開啟/關閉、新增/刪除某個模組或功能

一、簡介       不知不覺,短短几個月的時間,我已經寫了大大小小100篇部落格。短短几個月的時間,見證了我的努力、我的收穫、我的學習效率。從一開始的零基礎,到現在我需要了解整個專案的設計架構,才能來滿足我的設計需求。      

c語言資料結構應用-陣列佇列無鎖佇列執行緒的使用

一、背景 上篇文章《c語言資料結構實現-陣列佇列/環形佇列》講述了陣列佇列的原理與實現,本文編寫一個雙執行緒進行速度測試 二、相關知識 多執行緒程式設計介面: 1) 建立執行緒 pthread_create 函式 SYNOPSIS #include <