1. 程式人生 > >【C++】C++類的學習(一)——初識類

【C++】C++類的學習(一)——初識類

前言

       C++在C語言的基礎上做了一些改進,使得C++具有了面向物件程式設計(Object Oriented Programming,OOP)的特性。其中最重要的改進就是提供了類的概念。可以說學習了C++卻不會使用類的話,那麼就沒有學習到C++的精髓。

       在接下來的幾篇博文中,我將梳理一下自己學習C++中類的學習心得。類中涵蓋的知識點非常龐雜,我不會把每個細節都寫出來,我會沿著主線由淺入深來梳理,希望對看到這些博文且想了解類的你有所幫助。

初探類

      類的基本思想是資料抽象封裝。資料抽象是一種把介面和實現分離的程式設計技術。類的介面包括使用者所能夠執行的操作,類的實現包括類的資料成員、負責介面實現的函式體和各種私有函式。

      封裝實現了類的介面和實現的分離。封裝隱藏了類的實現,封裝過後,使用者只能訪問類的介面,而不能訪問類的實現。

     類是一種將抽象轉換為使用者定義型別的C++工具,它將資料表示和操縱資料的方法組合成一個整體。例如一個日常生活時間類,時間物件有兩個屬性,小時和分鐘,根據需要應該能夠對每個日常事務所花的時間進行操作和顯示。操作和顯示就需要類的介面函式。

      一般的類由兩部分組成:

      1. 類宣告:以資料成員的方式描述資料部分,以成員函式(被稱為方法)的方式描述介面函式。

      2. 類方法定義:描述如何實現類成員函式。

      簡單地說,類宣告給出了類的框架,而方法定義給出了類的細節。

私有成員與公有成員

       在下面的程式碼中聲明瞭一個Time類;類中有兩個關鍵字privatepublic,它們描述了程式對類的成員的訪問控制。由於隱藏資料是OOP的主要目的之一,所以資料成員一般放在private部分,而介面函式則放在public部分。

#ifndef MYTIME_H
#define MYTIME_H
#include <iostream>

using namespace std;

class Time
{
	//----------私有成員,類中的成員預設是私有的
private:
	int hours;
	int mintues;

	//----------共有成員
public:
	Time();                                                       //預設建構函式
	Time(int h, int m = 0);                                       //顯式建構函式
	Time(const Time &);                                           //拷貝建構函式
	~Time();                                                      //解構函式
	void AddMin(int m);
	void AddHour(int h);

	void reset(int h = 0, int m = 0);

	//------展示函式show()     //在const函式中不可呼叫非const函式成員
	void Time::show() const
	{
		cout << "hours:" << hours << "  " << "mintues:" << mintues << "  "<<endl;
	}

};


//-------時間重置,行內函數
inline void Time::reset(int h, int m)
{
	hours = h;
	mintues = m;
}


#endif

       使用類物件的程式可以直接訪問類的公有成員,但是不能直接訪問私有成員,要訪問私有成員則需要公有成員間接地訪問。例如在程式中定義一個Time類物件eating。可以通過eating訪問公有成員show()函式,而不能直接用eating訪問hours。

Time eating(1, 45);

eating.show();                      //合法;
eating.hours;                       //非法,不能直接訪問私有成員。

注:類的成員預設是私有的,但是為了嚴謹一般還是用private關鍵字註明,而結構體的成員預設是公有的。

成員函式的實現

1.    在類外定義一個成員函式時,需要使用域解析運算子(::)來標識函式所屬的類。這意味著,不同的類中,可以定義同樣的成員函式而互不影響。

例如:

void Time::AddMin(int m)

{
mintues += m;
hours += mintues / 60;
mintues %= 60;
}

2.    在宣告一個類時,可以將成員函式的定義直接放入類中,此時函式預設是一個行內函數,不需要新增域解析符。但是為了方便程式碼閱讀,一般不會將成員函式直接在類中實現。

       在上面的程式碼中,成員函式show()就直接定義在了類的定義體中。

3.    也可以將函式的實現寫進類宣告的標頭檔案中,但是一定要新增inline關鍵字,在C++中的標頭檔案(.h詳解(2中曾經提到過原因,如果不讓函式成為行內函數,當頭檔案被多個原始檔引用時,會出現重定義。(有疑惑的可以點選上面的連結進入閱讀博文)

       上面程式碼中的,reset()函式就是採用行內函數的方式定義在了類定義的標頭檔案中。

類物件使用類成員

   物件使用成員函式時使用成員運算子: .

   例如:Time的一個物件eating呼叫show()函式。

eating.show();

類的const成員

       為了保證資料的安全,在類的成員函式不修改物件的值時,應該儘量將成員函式定義為const成員函式。定義一個const類物件與定義一個const普通物件一樣,在物件前加上const 關鍵字。

      定義一個的const成員函式時const關鍵字是放在括號後面的,他的意思是這個函式不不能修改呼叫它的物件的值。與返回值是否是常量無關。

void Time::show() const    //const關鍵字被放在了函式名括號的後面
{
	cout << "hours:" << hours << "  " << "mintues:" << mintues << "  "<<endl;
}

      一個const物件是無法呼叫非const成員函式的,以免非const成員函式修改const物件的資料,這無疑降低了程式出錯的可能性,而非const物件是可以呼叫const成員函式的。以下面的程式碼為例。

Time swiming(0, 45);                 //非const物件
const Time study(8, 5);              //const物件只能呼叫const成員函式。
study.reset(0,0);                    //非法,const物件無法呼叫非const成員函式。

study.show();                        //合法,show()是const成員函式。
swiming.show();                      //合法;

       當然了,在const函式中修改物件的值是非法的,編譯器無法通過。

成員初始化規則

  • const修飾的變數定義後就不能更改了,因此,需要使用初始化列表來初始化。
  • 引用在進行初始化後就不會再改變,因此,也需要使用初始化列表來初始化。
  • 資料成員是物件時候,需要呼叫建構函式進行初始化(繼承時呼叫基類建構函式)
  • static與類有關,不需要使用初始化列表。
  • 指標的值在初始化後可以改變,即指向其它的儲存單元,因此,也不要使用初始化列表。

程式碼

      為了方便大家的理解,在這裡貼出所有程式碼

//----mytime.h
#ifndef MYTIME_H
#define MYTIME_H
#include <iostream>

using namespace std;

class Time
{
	//----------私有成員,類中的成員預設是私有的
private:
	int hours;
	int mintues;

	//----------共有成員
public:
	Time();                                                       //預設建構函式
	Time(int h, int m = 0);                                       //顯式建構函式
	Time(const Time &);                                           //拷貝建構函式
	~Time();                                                      //解構函式
	void AddMin(int m);
	void AddHour(int h);

	void reset(int h = 0, int m = 0);

	//------展示函式show()     //在const函式中不可呼叫非const函式成員
	void Time::show() const    //const關鍵字被放在了函式體的後面
	{
		cout << "hours:" << hours << "  " << "mintues:" << mintues << "  "<<endl;
	}

};


//-------時間重置,行內函數
inline void Time::reset(int h, int m)
{
	hours = h;
	mintues = m;
}


#endif
//--mytime.cpp

#include <iostream>
#include "mytime.h"

using namespace std;

//-------預設建構函式
Time::Time()
{
	hours = mintues = 0;
	cout << "呼叫預設建構函式" << endl;
}

//------顯式的建構函式
Time::Time(int h, int m) :hours(h), mintues(m)
{
	cout << "呼叫顯式建構函式" << endl;
}

//------拷貝建構函式
Time::Time(const Time &t)
{
	hours = t.hours;
	mintues = t.mintues;
	cout << "呼叫拷貝建構函式" << endl;
}

//------解構函式
Time::~Time()
{
	cout << "呼叫了解構函式" << endl;
}

//-------小時相加
void Time::AddHour(int h)
{
	hours += h;
}

//------分鐘相加
void Time::AddMin(int m)
{
	mintues += m;
	hours += mintues / 60;
	mintues %= 60;
}
//---test.cpp
#include <iostream>
#include "mytime.h"

using namespace std;

const void fun()
{
	cout << 1 << endl;
}


int main()
{

	Time eating(1, 45);

	eating.show();                        //合法;
	//eating.hours;                       //非法,不能直接訪問私有成員。

	Time swiming(0, 45);                   //非const物件
	const Time study(8, 5);                //const物件只能呼叫const成員函式。
	//study.reset(0,0);                    //非法,const物件無法呼叫非const成員函式。

	study.show();                         //合法,show()是const成員函式。
	swiming.show();                       //合法;

	system("pause");
	return 0;
}

執行結果

結果分析

      上面的結果和程式碼中都可以看到建構函式,解構函式以及拷貝建構函式,因為這三種函式是類非常重要的成員函式,因此下次進行單獨講解。

已完。。

參考書籍《C++  Primer 第五版》、《C++ Primer Plus 第六版》

相關部落格