1. 程式人生 > >一步一步學習C++(類)之虛擬函式和純虛數

一步一步學習C++(類)之虛擬函式和純虛數

1、該函式必須與基類的虛擬函式有相同的名稱
2、該函式必須與基類的虛擬函式有相同的引數個數和相對應的引數型別
3、該函式必須與基類的虛擬函式有相同的返回值,或滿足型別相容規則的指標,引用型返回值。

4、如果派生類的函式滿足以上三個條件系統就會自動把其定為虛擬函式。這時派生類的虛擬函式便覆蓋了基類的虛擬函式,不僅如此派生類中的虛擬函式還會隱藏基類中同名函式的所有其他過載形式。

5、只有虛擬函式是動態繫結的,如果派生類需要修改基類的行為,即重寫與基類的函式同名的函式,就應該在基類中將相應的函式宣告為虛擬函式。而基類中宣告的非虛擬函式,通常代表不希望被派生類改變的功能,也不能實現多型。因此一般不要重寫繼承而來的非虛擬函式。

6、在重新繼承來的虛擬函式時,如果有預設形參值,千萬不要定義不同的值。原因是誰然虛擬函式是動態繫結的,但是預設形參值是靜態繫結的,也就是說,通過一個指向派生類物件的基類指標,可以訪問到派生類的虛擬函式,但預設形參值卻只能來自基類的定義;

// VirtualAndDT.cpp : 定義控制檯應用程式的入口點。
//

#include "stdafx.h"
#include<iostream>
using namespace std;

//虛擬函式經典列子
class B0
{
public:
	virtual void display()//如果沒有虛擬函式 下面的main函式內容將輸出都是基類的函式
	{
		cout <<"我是顯示頁面B0" << endl;
	}

};
class B1:public B0
{
public:
	void display()
	{
		cout << "我是顯示頁面B1" << endl;
	}
};

void fun(B0 *p)
{
	p->display();
}

void main()
{
	B0 *p;//基類指標
	B0 b0;
	B1 b1;
	p = &b0;
	fun(p);
	p = &b1;
	fun(p);
	system("pause");
}

     虛擬函式是動態繫結的,但是預設形參值是靜態繫結的,也就是說,通過一個指向派生類物件的基類指標,可以訪問到派生類的虛擬函式,但預設形參值卻只能來自基類的定義

// VirtualAndDT.cpp : 定義控制檯應用程式的入口點。
//

#include "stdafx.h"
#include<iostream>
using namespace std;

//虛擬函式
class B0
{
public:
	virtual void display(int a=5)
	{
		cout <<  "我是顯示頁面B0"  << a << endl;
	}
};
class B1:public B0
{
public:
	void display(int a=6)
	{
		cout <<  "我是顯示頁面B1" << a << endl; // 注意輸出是 5
	}
};
class B2:public B1
{
public:
	void display(int a = 7) //  注意輸出是5
	{
		cout <<  "我是顯示頁面B2" << a<< endl;
	}
};
void fun(B0 *p)
{
	p->display();
}
void main()
{
	B0 *p;
	B0 b0;
	B1 b1;
	B2 b2;
	p = &b0;
	fun(p);
	p = &b1;
	fun(p);
	p=&b2;
	fun(p);
	system("pause");
}


// VirtualAndDT.cpp : 定義控制檯應用程式的入口點。
//

#include "stdafx.h"
#include<iostream>
using namespace std;

class B0
{
public:
	virtual void display()  //顯示定義虛擬函式
	{
		cout <<  "我是顯示頁面B0" << endl;
	}
};
class B1:public B0
{
public:
	void display()    //預設虛擬函式
	{
		cout <<  "我是顯示頁面B1" << endl;
	}
};
class B2:public B1
{
public:
	void display()
	{
		cout <<  "我是顯示頁面B2" << endl;
	}
};
void fun(B0 *p)
{
	p->display();
}
void main()
{
	B0 *p;
	B0 b0;
	B1 b1;
	B2 b2;
	p = &b0;
	fun(p);
	p = &b1;
	fun(p);
	p=&b2;
	fun(p);
	system("pause");
}


二、純虛擬函式

純虛擬函式是在基類中只宣告虛擬函式而不給出具體的函式定義體,將它的具體定義放在各派生類中,稱此虛擬函式為純虛擬函式.通過該基類的指標或引用就可以呼叫所有派生類的虛擬函式,基類只是用於繼承,僅作為一個介面,具體功能在派生類中實現.

純虛擬函式的宣告如下:(注:要放在基類的定義體中)

   virtual 函式原型=0;

聲明瞭純虛擬函式的類,稱為抽象類。

  • 抽象類中可以有多個純虛擬函式

  • 不能宣告抽象類的物件,但可以宣告指向抽象類的指標變數和引用變數

  • 抽象類也可以定義其他非純虛擬函式

  • 如果派生類中沒有重新定義基類中的純虛擬函式,則在派生類中必須再將該虛擬函式宣告為純虛擬函式

  • 從抽象類可以派生出具體或抽象類,但不能從具體類派生出抽象類

  • 在一個複雜的類繼承結構中,越上層的類抽象程度越高,有時甚至無法給出某些成員函式的實現,顯然,抽象類是一種特殊的類,它一般處於類繼承結構的較外層

  • 引入抽象類的目的,主要是為了能將相關類組織在一個類繼承結構中,並通過抽象類來為這些相關類提供統一的操作介面

class B0
{
public:
	virtual void display() const =0;//如果沒有純虛擬函式 下面的main函式內容將輸出都是基類的函式
	
};
class B1:public B0
{
public:
	void display() const
	{
		cout <<  "我是顯示頁面B1" << endl;
	}
};

void fun(B0 *p)
{
	p->display();
}
void main()
{
	B0 *p;
	//B0 b0;
	//error C2259: “B0”: 不能例項化抽象類
	 B1 b1;
	//p = &b0;
	//fun(p);
	p = &b1;
	fun(p);
	system("pause");
}

/*
virtual void display() const =0;//純虛擬函式
(1)=0說明它是純虛擬函式
(2)const表明不能修改其資料成員
const 和 =0 沒有關係,要分開理解   
 成員函式後面用 const 修飾,通俗的理解就是在這個函式內不能修改類的成員變數,除非那個成員變數是   mutable   的
  */

class B1:public B0
{
public:
	void display() const
	{
		cout <<  "我是顯示頁面B1" << endl;
		x = 0;
		/*error C2166: 左值指定 const 物件*/
	}
private:
	int x;
};


相關推薦

學習C++虛擬函式虛數

1、該函式必須與基類的虛擬函式有相同的名稱 2、該函式必須與基類的虛擬函式有相同的引數個數和相對應的引數型別 3、該函式必須與基類的虛擬函式有相同的返回值,或滿足型別相容規則的指標,引用型返回值。 4、如果派生類的函式滿足以上三個條件系統就會自動把其定為虛擬函式。這時派生類

Angular學習筆記輔助路由路由守衛

輔助路由 啟用後,在任何頁面都會顯示相關的輔助路由元件。 輔助路由的語法分3步 1.頁面插座,輔助路由的寫法是帶有name屬性 <router-outlet></router-outlet> <router-

跟我學習lucene6---lucene索引優化多執行緒建立索引

這兩天工作有點忙,部落格更新不及時,請大家見諒; 前面瞭解到lucene在索引建立的時候一個IndexWriter獲取到一個讀寫鎖,這樣勢在lucene建立大資料量的索引的時候,執行效率低下的問題; 磁碟空間大小,這個直接影響索引的建立,甚至會造成索引寫入提示完成,但是沒

跟我學習lucene11---lucene搜尋高亮顯示highlighter

highlighter介紹 這幾天一直加班,部落格有三天沒有更新了,望見諒;我們在做查詢的時候,希望對我們自己的搜尋結果與搜尋內容相近的地方進行著重顯示,就如下面的效果 這裡我們搜尋的內容是“一步一步跟我學習lucene”,搜尋引擎展示的結果中對使用者的輸入資訊進行了配色方

跟我學習lucene7---lucene搜尋IndexSearcher構建過程

最近一直在寫一步一步跟我學習lucene系列(http://blog.csdn.net/wuyinggui10000/article/category/3173543),個人的部落格也收到了很多的訪問量,謝謝大家的關注,這也是對我個人的一個激勵,O(∩_∩)O哈哈~,個人感

C++

類 具有相同屬性的一類事物,將不同型別的資料和與這些資料相關的操作封裝在一起,類的例項是物件。 定義: class 類名//類名一般採取首字母大寫的格式,成員訪問許可權的宣告出現順序無要求。 { public:(public成員) private:(privat

MySQL學習筆記4-- jdbc異常處理工具抽取

一:異常處理 在前面的學習中,所有的異常全部都是使用throws方法解決的,現在嘗試將異常在程式內部進行處理。 為什麼要在程式內部處理異常? 因為採用throws方法,一旦產生異常,程式會停止執行,並將異常丟擲,但是此時程式內的資源並沒有釋放出來,而Con

《資料結構與演算法 python語言描述》學習筆記————抽象資料型別Python

第一部分:學習內容概要 抽象資料型別 Python的類 第二部分:學習筆記 抽象資料型別   1.抽象資料型別(Abstract Data Type,ADT),通過一套介面闡述說明這一程式部分的可用功能,但不不限制功能的實現方法。      2.抽象資料型

C++ 物件大小計算含有虛擬函式

五、包含虛擬函式的類         包含虛擬函式的類,物件生成時,會在類物件當中插入一個指標,這個指標稱做虛擬函式表指標,簡稱虛表指標(vPtr)。該指標指向一個虛擬函式表(簡稱虛表),虛擬函式表中儲存了虛擬函式的入口地址。基類當中有虛擬函式時,會產生該虛擬函式表;建立基

《機器學習實戰》學習筆記

轉載請註明作者和出處:http://blog.csdn.net/john_bh/ 執行平臺: Windows Python版本: Python3.6 IDE: Sublime text3

C#學習筆記009:匿名型別隱式區域性變數

一、概述        在C#3.0中,對語言方面做了很多方面的增強,其中的兩項是匿名型別和隱式區域性變數的宣告。跟這兩項都相關的有一個上下文關鍵字var。 二、匿名型別       我們常見的在C#中定義一個變數的語法格式是:資料型別   變數  =  變數值;,這樣

C語言學習總結1-遞迴函式的理解

啥是遞迴? 即是該函式呼叫它本身自己,這種呼叫過程稱為遞迴。 遞迴可以相當於迴圈,所以想結束遞迴,就必須有終止遞迴的條件測試部分,否則就會出現無限遞迴(即無限迴圈)。同時,這也是使用遞迴的難點

C語言學習筆記—— 運算子、表示式語句

一、運算子1、賦值運算子:=        賦值表示式的目的是把值儲存到記憶體位置上,用於儲存值的資料區域統稱為資料物件,使用變數名是標識物件的一種方法。物件指的是實際的資料儲存,左值是用於標識和定位儲存位置的標籤,右值指的是能賦值給可修改左值的量。void example1

Objective-C學習筆記——迴圈語句fordo-while的使用

      在OC中,除了while這種迴圈方式外,還有另外for迴圈和do-while迴圈,它們在不同的業務邏輯下會有不同的作用。可以和C語言和Java對比著學習。(一)程式碼一:int main(int argc, const char * argv[]) { @

SQLite學習筆記-- 事務基本概念程式碼實現C++實現

1.事務基本概念 什麼是事務? 事務是使用者定義的一些列資料操作,這些操作是一個完整的不可分的工作單元。一個事務要麼全部執行,要麼全部不執行。 檢視案例 例如銀行的轉賬操作,張三向李四轉賬1000元。該事務包含以下兩個操作: 1.張三賬戶上扣除1000

通過例子學習C++最小公倍數

本文是通過例子學習C++的第二篇,通過這個例子可以快速入門c++相關的語法。 題目要求:輸入兩個整數,求其最小公倍數。 解答方法一:兩個數的最小公倍數,是這兩個數中的大數,或者是這2個數的倍數中的最小數字。 這兩個數字用num1和num2儲存,max表示其中最大數字。如果max能同時整除num1和num2,則

通過例子進階學習C++計算2的64次方,不服寫寫看

本文是通過例子學習C++的第四篇,通過這個例子可以快速入門c++相關的語法。 1.乍一看題目非常簡單,簡單思考一下,可以通過for迴圈實現: #include <iostream> using namespace std; int main() { int num = 1; for

通過例子進階學習C++你真的能寫出約瑟夫環麼

本文是通過例子學習C++的第六篇,通過這個例子可以快速入門c++相關的語法。 1.問題描述 n 個人圍坐在一個圓桌周圍,現在從第 s 個人開始報數,數到第 m 個人,讓他出局;然後從出局的下一個人重新開始報數,數到第 m 個人,再讓他出局......,如此反覆直到所有人全部出局為止。 2.問題分析及用陣列求解

通過例子進階學習C++CMake專案通過模板庫實現約瑟夫環

本文是通過例子學習C++的第七篇,通過這個例子可以快速入門c++相關的語法。 1.問題描述 回顧一下約瑟夫環問題:n 個人圍坐在一個圓桌周圍,現在從第 s 個人開始報數,數到第 m 個人,讓他出局;然後從出局的下一個人重新開始報數,數到第 m 個人,再讓他出局......,如此反覆直到所有人全部出局為止。 上

bfzwjeqjSpriNgMc學習系列3url

ref htm 學習 pri blank url lan get 系列 bfzwjeqjSpriNgMc學習系列(3)之url χ絳 bfzwjeqjSpriNgMc學習系列(3)之urlbfzwjeqjSpriNgMc學習系列(3)之url