1. 程式人生 > >【C++】類和物件(二)

【C++】類和物件(二)

 一、this指標

 關於this指標的一個精典回答:

       當你進入一個房子後,
       你可以看見桌子、椅子、地板等,
       但是房子你是看不到全貌了。
       對於一個類的例項來說,
       你可以看到它的成員函式、成員變數,
       但是例項本身呢?

       this是一個指標,它時時刻刻指向你這個例項本身。

       (一)this 指標:隱含在非靜態成員函式中的特殊指標,它是當前正在呼叫此成員函式的物件的指標。

       (二)this指標的作用:成員函式對成員變數的引用實際是通過this指標訪問的,也就是說,成員變數 this->成員變數;另外,如果成員函式需要訪問當前物件,也可以通過this指標,*this就是當前物件。

       (三)this 指標的特性:1)this 指標的型別:類型別 * const

                                           2)this 指標並不是物件本身的一部分,不影響 sizeof 的結果

                                           3)this 指標的作用域在類“成員函式”的內部

                                           4)this 指標是“類成員函式”的第一個預設隱含引數,編譯器自動維護傳遞,類編寫者不                                                           能顯示傳遞

                                           5)只有在類的非靜態成員函式中才可以使用 this 指標,其它任何函式都不可以

二、六個預設的成員函式

 類的六個預設成員函式為建構函式,拷貝建構函式、解構函式、賦值操作符過載、取地址操作符過載、const修飾的取地址操作符過載

       (一)建構函式

//日期類的建構函式
Date(int year,int month,int day)
	:_year(year)
	, _month(month)
	, _day(day)
{
        cout << "Date(int):" << this << endl;
}

       一)建構函式的定義:函式名與類名相同,沒有返回值型別,建立類型別物件時,由編譯器自動呼叫,在物件的什麼週期內只調用一次。

       二)建構函式的特性:1)函式名與類名相同

                                       2)沒有返回值

                                       3)新物件被建立時,由編譯器自動呼叫,且在物件的生命週期內僅呼叫一次

                                       4)建構函式可以過載,實參決定了呼叫那個建構函式

                                       5)無參建構函式和帶有預設值的建構函式都認為是預設的建構函式,並且預設的構造函                                                數只能有一個

                                       6) 有初始化列表(可以不用)

                                       7)沒有顯式定義時,編譯器會合成一個預設的建構函式

                                       8)建構函式不能用 const 修飾

                                       9)建構函式不能為虛擬函式

        三)建構函式的作用:構造和初始化物件、型別轉換

        四)隱式型別轉換

  什麼樣的建構函式有型別轉換的作用? 類的建構函式一定是單參的,如果不是單參其他的的引數要有預設值

        如何禁止隱式型別轉換? 在建構函式前加上explicit

        五)物件的初始化

class Date
{
public:
    Date(int year, int month, int day)
        :_year(year);
        ,_month(month)
        ,_day(day)   //上述三行就是物件的初始化
    {} 
private:
    int _year;
    int _month;
    int _day;    
};

 從上述日期類中不難看出,物件的初始化在初始化列表,以一個冒號開始,以逗號分隔資料成員列表,每個成員變數後面跟一個括號放初始值或表示式。

        必須在初始化列表初始化的有三類,引用成員變數、const 類型別常量、類裡面包含了另外一種類型別的物件(舉例:兩個類  A類  B類   B類包含A類物件,A類有不是預設的建構函式,把A類這個物件放在B類的初始化列表初始化)

       this指標可以在初始化列表中使用嗎?

答:函式體內進行的是賦值,而初始化列表進行的是初始化,這說明物件並不完整,所以不能通過this訪問。

       編譯器什麼時候合成建構函式?

如果編譯器感覺自己需要時再去合成預設的建構函式,有一下三種情況。

       1)如果A類中包含了B類的物件,前提:B類有預設的建構函式,A類沒有顯式定義自己的建構函式,編譯器                就會為A類合成預設的建構函式

       2)如果B類沒有預設引數,A類的建構函式就需要顯式的給出建構函式

       3)建立物件時需不需要給物件一個初始值,如果需要初始值就需要給出建構函式,一般情況下都要給出構造              函式

       注:顯式的意思,這個建構函式使用者有沒有自己定義。

       六)預設引數的概念在宣告或定義函式時為函式的引數指定的一個預設值。

        特性:1)帶預設值的引數必須放在引數列表最後面

                   2)一般放在宣告中(宣告、定義只能出現一次)

                   3)預設值必須是常量或全域性變數

                   4)C語言不支援

       (二)拷貝建構函式

//日期類的拷貝建構函式
Date(const Date& d)
	:_year(d._year)
	, _month(d._month)
	, _day(d._day)
{
	cout << this->_year << endl;
	cout << "Date(const Date&):" << this << endl;
}	

       一)拷貝建構函式的定義:只有單個形參,該形參是對本類型別物件的引用(常用const修飾)

       拷貝建構函式形參為 const 類型別的引用(舉例:日期類的拷貝建構函式 Date(const Date& d);)的原因?

       答:一般外部實參不需要改變d所對應的內容,如果外部實參需要改變d對應的實體,則不需要給出const。

       二)拷貝建構函式的特徵:1)特殊的建構函式,是建構函式的過載

                                                  2)必須使用類型別物件引用傳遞

                                                  3)如果沒有顯式定義,系統會自動合成(只實現了拷貝建構函式的功能)。

                                                       預設的拷貝建構函式會一次拷貝類的資料成員完成初始化

                                                  4)拷貝函式不能過載

       為什麼必須使用類型別物件引用傳遞?

     

 拷貝建構函式的呼叫場景(什麼時候呼叫)?

1)當用同類已存在的物件作為引數,建立物件時,由編譯器自動呼叫(例日期類,Date d1(2018);

            Date  d2(d1);)

       2)作為函式返回值

       3)物件例項化物件(例日期類,Date d1(2018);Date d2(d1);)

       拷貝建構函式什麼時候合成?

     

(三)解構函式

//解構函式
~Date()
{}

一)解構函式的概念解構函式與建構函式的功能相反,在物件出函式作用域之前被銷燬,由編譯器自動呼叫,完成一些類的資源清理和汕尾工作。

       二)解構函式的特性:1)解構函式的函式名與類名相同,且要在函式名前加上字元 ~

                                           2)解構函式沒有返回值

                                           3)一個類只有一個解構函式。若沒有顯式定義,編譯器會自動合成預設的解構函式

                                           4)物件生命週期結束時,編譯器會自動呼叫解構函式

                                           5)解構函式並不會刪除物件,只是對物件做一些資源清理

     三、運算子過載  

(一)運算子過載的概念:過載函式是具有特殊函式名的函式,關鍵字operator,後面接需要定義的操作符符號。

       為什麼要有運算子過載?運算子過載有什麼意義?

       答:看一下這兩個例子我想就能夠比較清楚的理解為什麼要有運算子的過載了。

              例一,比如你定義一個型別“學生,現在如果你把兩個“學生”型別的變數相加, 那系統怎麼知道你要怎麼加? 如果是數字的話,系統知道。那這個時候,你就要為“學生”這個型別過載加號運算子,然後在這個過載的方法裡實現相加的意義,比如“學生”型別的年齡相加,或是其它東西相加,這個就你自己定義了。

              例二,如果你定義了一個 “日期”類,想要把兩個日期類相加,系統同樣不清楚你要如何相加。這時候你就要為“日期”這個類過載加號運算子,在這個過載函式中實現兩個日期類的相加。

               綜上,也就是說運算子過載是為了適應不同的資料型別,並提高程式碼的執行效率還有使用簡單方便

       哪些運算子不能過載?


      (二)過載運算子需要注意的事項:

(1)不能通過連線其他符號來建立新的操作符。例如,[email protected]

      (2)過載操作符必須有一個類型別或者列舉型別的運算元。

      (3)用於內建型別的操作符,其含義不能改變。例如,內建的整形+,不能改變它的含義。

      (4)因為有一個隱含形參 this,所以類的過載函式看起來比操作符數數目少1。this 限定為第一個形參。

      (5)一般將算術操作符定義為非成員函式,將賦值運算子定義為成員函式,且操作符定義為非成員函式時,                  一般將其定義為類的友元。

      (6)== 和 != 操作符一定要成對過載使用。

      (7)前置++/--必須返回被增量或者減量的引用後置++/--操作符必須返回舊值,也就是返回值

      (8)輸入操作符>>和輸出操作符<<必須定義為類的友元函式

  (三)賦值操作符過載

//賦值操作符的過載
Date& operator=(const Date& d)
{
	if (this != &d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;

		return *this;
	}
}

      (四)取地址操作符過載

//取地址操作符的過載
Date* operator&()
{
	return this;
}

      (五)const修飾的取地址操作符過載       

//const 修飾的取地址操作符的過載
const Date* operator &()const
{
	return this;
}

     四、靜態成員 

(一)靜態成員的定義在類的成員資料或成員函式前加上 static 修飾的類成員,稱為類的靜態成員。

      (二)靜態成員的特徵

                1)靜態成員為所有類物件所共享,不屬於某個具體的例項。

                2)靜態成員可以用 類名: :靜態成員 . 靜態成員 /類名: :物件 . 靜態成員 來訪問。

                3)類靜態成員變數必須在類外定義,定義時不新增 static 關鍵字

                4)類的靜態成員函式沒有預設的 this 指標,因此靜態成員函式中不能使用任何非靜態成員

                5)靜態成員和類的普通成員一樣,有訪問限定符3種訪問級別,有返回值,能被const修飾

       靜態成員函式能夠呼叫非靜態成員函式嗎?非靜態成員函式可以呼叫類的靜態成員函式嗎?

       答:靜態成員函式不能呼叫非靜態成員函式,因為靜態成員函式沒有this指標,而呼叫成員函式的時候,實際是this->成員函式。非靜態成員函式可以呼叫靜態成員函式。

       靜態成員函式與普通成員函式,普通函式的區別?

       答:普通函式:屬於全域性函式,不受具體類和物件的限制,可以直接呼叫。

              普通成員函式:C++ 普通成員函式本質上是一個包含指向具體物件this指標的普通函式,即c++類的普通成員函式都隱式包含一個指向當前物件的this指標。

              在介紹靜態成員函式之前我們再認識一下靜態成員變數,類體中的資料成員的宣告前加上static關鍵字,該資料成員就成為了該類的靜態資料成員。靜態成員變數的性質:一,static型變數只被初始化一次,下次執行初始化語句會直接跳過;二,static 說明一個類的成員為靜態成員,經過static修飾的成員變數屬於這個類,不再僅僅屬於具體的物件。

             靜態成員函式: 類體中的成員函式的宣告前加上static關鍵字,該成員函式就成為了該類的靜態成員函式。靜態成員函式的性質,一,不可以呼叫類的非靜態成員;二,靜態成員函式不含this指標。 靜態成員函式屬於這個類,不再僅僅屬於具體的物件。因此類的靜態成員函式和類的普通成員函式的區別是:

            靜態成員函式不包含指向具體物件的this指標;普通成員函式包含一個指向具體物件的this指標。

     五、const型別成員

     (一)const型別成員的定義:類中用 const 關鍵字修飾的資料成員或者成員函式就稱為const型別成員。

      (二)const的使用場景

                 1)const修飾形參,一般和引用同時使用

                 2)const修飾返回值

                 3)const修飾類的資料成員,必須在建構函式的初始化列表中初始化

                 4)const修飾類的成員函式,實際上修飾的是隱含的this指標,表示類中不介意對類的任

                       何成員進行修改

                 5)在const修飾的成員函式中要對類的某個資料成員進行修改,該資料成員定義宣告必                                                須加mutable關鍵字

       注意事項:1)const物件(const成員函式內)只能呼叫const修飾的成員函式,不能呼叫非const成員函式

                         2)非const物件(非const成員函式內)既可以呼叫const成員函式,也可以呼叫非const成員函式

       const不能修飾static修飾的成員函式的原因?

       答:static修飾的成員函式沒有this指標。

       C語言中的const與C++中的const的區別?

       答:C語言中的const只能修飾變數,且被const修飾的變數還是變數。

              C++中const修飾的變數已經是常量,且C++中被const修飾的變數不僅是變數還具有巨集的特性。

       上述運用到的相關程式碼:

#include<iostream>
using namespace std;

class Time
{
public:
	//時間類的建構函式
	Time(int hour = 0, int minute = 0, int second = 0)
		:_hour(hour)
		, _minute(minute)
		, _second(second)
	{}
	//時間類的拷貝建構函式
	Time(const Time& t)
		:_hour(t._hour)
		, _minute(t._minute)
		, _second(t._second)
	{}

	
private:
	int _hour;
	int _minute;
	int _second;
};

class  Date
{
public:
	//日期類的建構函式
	Date(int year,int month,int day)
		:_year(year)
		, _month(month)
		, _day(day)
	{
		cout << "Date(int):" << this << endl;
	}
	//日期類的拷貝建構函式
	Date(const Date& d)
		:_year(d._year)
		, _month(d._month)
		, _day(d._day)
	{
		cout << this->_year << endl;
		cout << "Date(const Date&):" << this << endl;
	}                                              
	//this指標可以在初始化列表中使用嗎?
	//函式體內進行的是賦值,而初始化列表進行的是初始化,說明物件不完整,所以不能通過this訪問
	
	//賦值操作符的過載
	Date& operator=(const Date& d)
	{
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;

			return *this;
		}
	}

	//取地址操作符的過載
	Date* operator&()
	{
		return this;
	}

	//const 修飾的取地址操作符的過載
	const Date* operator &()const
	{
		return this;
	}

	//解構函式
	~Date()
	{}

private:
	int _year;
	int _month;
	int _day;

	Time _t;
};


int main()
{
	Date d1(2018, 6, 10);
	Date d2(d1); //直接傳物件 會接受類型別物件,
	             //如果物件非常大 通過值傳遞會產生臨時物件 
		     //效率低且浪費空間  因此傳類型別的引用  Date(Date& d);稱為拷貝建構函式
	return 0;
}

相關推薦

C++物件

 一、this指標  關於this指標的一個精典回答:       當你進入一個房子後,       你可以看見桌子、椅子、地板等,       但是房子你是看不到全貌了。       對於一個類的例項來說,       你可以看到它的成員函式、成員變數,       但是例

C++物件4

一、類的六個預設成員函式 下面是一個Date類,但是它類中什麼成員也沒有,這就是空類。但是它雖然看起來什麼都沒有,實際上不是的,在我們什麼都不寫的情況下,它會自動生成六個預設的成員函式。如圖所示的建構函式、解構函式、拷貝建構函式、賦值過載函式、普通物件取地址函式、const物件取地址函式這六個函

C++物件3—>> this指標

一、this指標的引入 我們在現實中,定義一個類都是根據一個需求來定義的。所以先來看一個常用的日期類 Date 。 class Date { public: void Print() { cout << _year << "-" << _month

C++物件2

一、類的作用域 類定義了一個新的作用域,類的所有成員都在類的作用域中。在類體外定義成員,需要使用 :: 作用域解析符 指明成員屬於哪個類域。否則找不到。 class person { public: void PrintfPersonInfo(); private: char _name

C++物件

定義成員函式 所有成員都必須在類內宣告,但是成員函式可以定義在類內也可以定義在類外。 std::string isbn() const { return bookno;} ??? isbn函式是如何獲得bookno成員所依賴的物件呢?緊隨引數列表之後

C++第八章 物件

【專案1 - 三角形類】下面設計一個三角形類,請給出各成員函式的定義 #include<iostream> #include<cmath> using namespace std; class Triangle {public: void Set

C++學習筆記——物件

設計一個類就是設計一個新的型別,應該考慮: 此型別的“合法值”是什麼? 此型別應該有什麼樣的函式和操作符? 新型別的物件該如何被建立和銷燬? 如何進行物件的初始化和賦值? 物件作為函式的引數如何以值傳遞? 誰將使用此型別的物件成員? 類定義的語法形式: clas

C++的朋友friend

我把你當朋友,你就能訪問我的一切(是真的一切);但你不將我當作朋友,我就不能訪問你的一切。 定義與使用 在類A中,用friend關鍵字可以將一個全域性函式宣告為該類的“朋友”,也可以將另一個類宣告為該類的“朋友”。 (1)friend宣告語句:位置自由,一般放在類體大括號的

Scala入門到精通——第七節:物件

本節主要內容 單例物件 伴生物件與伴生類 apply方法 應用程式物件 抽象類 單例物件 在某些應用場景下,我們可能不需要建立物件,而是想直接呼叫方法,但是Scala語言並不支援靜態成員,Scala通過單例物件來解決該問題。單例物件的建立方式如下:

C++的繼承protected

目錄 類的繼承 函式重寫 虛擬繼承 多重繼承 類的繼承 類的繼承的出現,是由於實際問題的需要。比如定義了一個男人類和女人類,這2個類之間有屬性或者函式的重疊,那程式碼就有點冗餘,所以為了解決這個問題,就將這些共有的屬性和函式抽取出來,形成一個新

JAVA_SE第四章 物件

九、排序1.冒泡2選擇3.插入排序:從第二個開始與前面所有已經排好序的序列進行比較,插入到對應位置              for(inti=1;i<arr.length;i++)  {  //第二個元素開始,每個元素與前面已經排好序的元素比較            

1、C++&物件/建構函式/拷貝建構函式/操作符過載/解構函式

一、C++類 & 物件     C++ 在 C 語言的基礎上增加了面向物件程式設計,C++ 支援面向物件程式設計。類是 C++ 的核心特性,通常被稱為使用者定義的型別。     類用於指定物件的形式,它包含了資料表示法和用於處理資料的方法。類中的資料和方法稱為類的成員。函式在

C++物件&&實現OFFSETOF巨集&&THIS指標

一.目錄   1.物件的相關知識   2.類的定義   3.類的例項化   4.類物件模型   5.模擬實現offsetof巨集   6.this指標 二.正文 1.物件的相關知識   C語言是面向過程的,關注的是過程,分析求解問題的步驟,通過函式呼叫逐步解決問題

C#——物件

一、類和物件的區別 類:類是模型,確定物件將會擁有的特徵(屬性)和行為(方法),類是物件的型別。 類是抽象的概念,僅僅是模板,比如說“人”類 物件是一個能看得到、摸得到的具體實體 物件可以叫做類的例項(Instance) 類不佔記憶體,物件才佔記憶體 二、類的定

C++物件

1.物件的相關知識   C語言是面向過程的,關注的是過程,分析求解問題的步驟,通過函式呼叫逐步解決問題。   C++是面向物件的,關注的是物件,將一件事拆分成不同的物件,靠物件之間的互動完成。   物件:任何一個物件都應該具有兩個要素,即屬性和行為,物件是由一組屬性和行為構成的。如現實生活中的手機就是一個物

C++物件&&實現OFFSETOF巨集&&THIS指標

一.目錄   1.物件的相關知識   2.類的定義   3.類的例項化   4.類物件模型   5.模擬實現offsetof巨集   6.this指標 二.正文 1.物件的相關知識   C語言是面向過程的,關注的是過程,分析求解問題的步驟,通過函式呼叫逐步解

C++ 物件

目錄 類 類的引入 類的定義 訪問限定符 封裝 類的作用域 類的例項化 引出 C語言是面向過程的,關注的是過程,分析出求解問題的步驟,通過函式呼叫逐步解決問題。C++是基於面向物件的,關注的是物件,將一件事情拆分成不同的物件,靠物

C#物件——部分類

        partial關鍵字允許把類、結構、方法或介面放在多個檔案中。一般情況下,某種型別的程式碼生成器生成了一個類的某部分,所以把類放在多個檔案中是有益的。假定要給類新增一些從工具中自動生成的內容。如果重新執行該工具,前面所做的修改就會丟失。partial關鍵字有

C#結構、棧堆、值型別引用型別、里氏替換

目錄 舉例: 一、類和結構的區別: 二、棧和堆的區別: 1.官方解讀: 棧: 是編譯期間就分配好的記憶體空間,因此程式碼中必須就棧的大小有明確的定義; 區域性值型別變數、值型別引數等都在棧的記憶體中。 堆:

C++初識:物件2

在之前的文章裡,我們出初步瞭解了,什麼是類,類如何定義,類的大小怎麼計算等 一個空類裡面什麼也沒有,但是它並非是什麼也沒有,只要是類,它就有6個預設的成員函式: 1.建構函式 2.解構函式 3.拷貝建構函式 4.賦值操作符過載 5.取地址操作符過載 6.co