天天看點

第3章 類和對象(1)類和對象(1)

類和對象(1)

一、類和對象的基本概念

1.結構體與類

結構體的擴充

(1)C++語言對結構體類型進行了擴充,它不僅可以含有不同類型的資料,而且還可以含有函數。

(2)在C++中,通常把結構體中的資料稱為資料成員,把函數稱為成員函數。

用擴充的結構體類型求複數的絕對值
#include<iostream>
#include<cmath>
using namespace std;
struct Complex{//聲明了一個名為Complex的結構體類型
	double real;//資料成員,複數的實部
	double imag;//資料成員,複數的虛部
	void init(double r,double i){//成員函數,給real和image賦初值
		real=r;
		imag=i;
		}
	double abscomplex(){//成員函數,求複數的初始值
		double t;
		t=real*real+imag*imag;
		return sqrt(t);
	}
};
int main()
{
	Complex A;//定義結構體的Complex的變量A
	A.init(1.1,2.2);//調用成員函數init,給real和image賦初值
	cout<<"複數的絕對值是:"<<A.abscomplex()<<endl;//調用成員函數abscomplex
	return 0;
}
程式運作結果如下:
複數的絕對值是:2.45967
           

類的聲明

類與結構體的擴充形式非常相似,例如,上面的結構體類型Complex可以改寫成如下:
……
using namespace std;
class Complex{//用關鍵字class取代結構體的struct,聲明了一個名為Complex的類
double real;
……
           

類類聲明的一般形式如下:

class 類名{
	[private:]
	私有成員資料和成員函數
	public:
	公有資料成員和成員函數
};
           

2.成員函數的定義

類的成員函數是函數的一種,它也有函數名傳回值類型和參數表,用法與普通函數基本是一樣的,隻是它屬于一個類的成員。

成員函數的第一種定義:在類聲明中隻給出成員函數的原型,而将成員函數的定義放在類的外部。

傳回值類型 類名::成員函數名(參數表)
{
    函數體
}
           
表示坐标點的類Point可聲明如下:
class Point{
	public:
		void setpoint(int,int);//設定坐标點的成員函數setpoint的函數原型
		int getx();//取x坐标點的成員函數getx的函數原型
		int gety();//取y坐标點的成員函數gety的函數原型
	private:
		int x,y;
};
void Point::setpoint(int a,int b)//在類外定義成員函數setpoint
{
	x=a;
	y=b;
}
int Point::getx()//在類外定義成員函數getx
{
	return x;
} 
int Point::gety()//在類外定義成員函數gety
{
	return y;
}

           

成員函數的第二種定義方式是:将成員函數直接定義在類的内部。

成員函數的第三種定義方式是:為了書寫清晰,在類聲明中隻給出成員函數的原型,而将成員函數的定義放在類的外部。但是在類内函數原型聲明前或在類外定義成員函數前冠以關鍵字inline,以此顯式地說明這是一個内聯函數。這種定義内聯函數的方法稱為顯式定義。

3.對象的定義及使用

類與對象的關系

C++把類的變量叫做類的對象,對象也稱為類的執行個體。

對象的定義

(1)在聲明類的同時,直接定義對象,即在聲明類的右花括号“}”後,直接寫出屬于該類的對象名表。

(2)聲明了類之後,在使用時再定義對象。定義對象的格式與定義基本資料類型變量的格式一緻,其一本形式如下:

類名 對象名1,對象名2,……;

說明:

聲明了一個類便聲明了一種類型,它并不接收和存儲具體的值,隻作為生成具體對象的一種“樣闆”,隻有定義了對象後,系統才為對象配置設定存儲空間,以存放對象中的成員。

對象中成員的通路

不論是資料成員,還是成員函數,隻要是公有的,在類的外部可以通過類的對象進行通路。通路對象中的成員有以下三種方法。

(1)通過對象名和對象選擇符通路對象中的成員。

對象名.資料成員名

對象名.成員函數名[(實參表)]

其中“ . ”叫做對象選擇符,簡稱點運算符。

(2)通過指向對象的指針通路對象中的成員

在定義對象時,若我們定義的是指向此對象的指針,則通路此對象的成員時,不能用“ . ”操作符,而應使用“->”操作符。

(3)通過對象的引用通路對象中的成員

如果為一個對象定義了一個引用,也就是為這個對象起了一個别名。是以完全可以通過引用來通路對象中的成員,其方法與通過對象名來通路對象中的成員時相同的。

4.類的作用域和類成員的通路屬性

二、構造函數和析構函數

構造函數是屬于某一個類的,它可以由使用者提供,也可以由系統自動生成。析構函數,當撤銷類的對象時,析構函數就回收存儲空間,并做一些善後工作。

1.對象的初始化和構造函數

構造函數是一種特殊的成員函數,它主要用于為對象配置設定空間,進行初始化。

(1)構造函數的名字必須以類名相同,而不能由使用者任意命名。

(2)它可以有任意類型的參數,但不能具有傳回值類型。它不需要使用者來調用,而是在建立對象時自動執行的。

為類Complex建立一個構造函數
class Complex {
	private:
	double real;//表示複數的實部
	double imag;//表示複數的虛部
	public:
	Complex (double r,double i)//定義構造函數,其名與類名相同
	{
		real=r;imag=i;//在構造函數中,對私有資料real和image指派
	}
	double abscomplex()
	{
		double t;
		t=real*real+imag*imag;
		return sgrt(t);
		}
	};
           

在建立對象的同時,采用構造函數給資料成員賦初值,通常有以下兩種形式。

形式1:

類名 對象名[(實參表)];

這裡的“類名”與構造函數名相同,“實參表”是為構造函數提供的實際參數。

形式2:

類名 * 指針變量名=new 類名[(實參表)];

這是一種使用new運算符動态建立對象的方式。

說明:

(1)構造函數的名字必須以類名相同,否則編譯程式将它當作一般的成員函數來處理。

(2)構造函數沒有傳回值,在定義構造函數時,是不能說明它的類型的,甚至說明為void類型也不行。

(3)與普通的成員函數一樣,構造函數的函數體可寫在類體内,也可寫在類體外。

(4)構造函數的作用主要是用來對對象進行初始化,使用者根據初始化的要求設計函數體和函數參數。

(5)構造函數一般聲明為公有成員,但它也不需要也不能像其他成員函數那樣被顯式地調用,它是在定義對象的同時被自動地調用的,而且隻執行一次。

(6)在實際應用中,通常需要給每個類定義構造函數。如果沒有給類定義構造函數,則編譯系統自動地生成一個預設構造函數。

(7)構造函數可以不帶參數。

2.用成員初始化清單對資料成員初始化

不在函數體内用指派語句對資料成員初始化,而是在函數首部實作的。

帶有成員初始化清單的構造函數的一般形式如下:

類名 :: 構造函數名([參數表])[: (成員初始化清單)]

{

// 構造函數體

}

成員初始化清單的一般形式為:

資料成員名1(初始值1),資料成員名2(初始值2),……

3.構造函數的重載

(1)如果在類中使用者沒有定義構造函數,系統會自動提供一個函數體為空的預設構造函數。

(2)盡管一個類中可以包含多個構造函數,但對于一個對象而言,建立對象時隻執行其中的一個構造函數。

4.帶預設參數的構造函數

(1)如果構造函數在類的聲明外定義,那麼預設參數應該在類内聲明構造函數原型時指定,而不能在類外構造函數定義時指定。

(2)如果構造函數的全部參數都指定了預設值,則在定義對象時可以指定1個或幾個實參,也可以不給出實參,這時的構造函數也屬于預設構造函數。

(3)在一個類中定義了全部是預設參數的構造函數之後,不能再定義重載構造函數。

5.析構函數

析構函數有以下一些特點:

(1)析構函數名與類名相同,但它前面必須加一個波浪号(~)。

(2)析構函數不傳回任何值。在定義析構函數時,是不能說明它的類型的,甚至說明為void類型也不行。

(3)析構函數沒有參數,是以不能被重載。一個類可以有多個構造函數,但是隻能有一個析構函數。

(4)撤銷對象時,編譯系統會自動地調用析構函數。

說明:

(1)每個類必須有一個析構函數。若沒有顯式地為一個類定義析構函數,則編譯系統會自動生成一個預設析構函數。

(2)除了在主程式結束(或調用exit函數)時,對象被撤銷,系統會自動調用析構函數外,在以下情況,析構函數也會被調用:

A:如果一個對象被定義在一個函數體内,則當這個函數被調用結束時,該對象将釋放,析構函數被調用。

B:若一個對象是使用new運算符動态建立時,在使用delete運算符釋放它時,delete會自動調用析構函數。

三、對象數組與對象指針

1.對象數組

所謂對象數組是指一個數組元素都是對象的數組,也就是說,若一個類有若幹個對象,我們把這一系列的對象用一個數組來存放。對象數組的元素是對象,不僅具有資料成員,而且還有成員函數。

定義一個一維數組的格式如下:

類名 數組名 [下标表達式];

在使用對象數組時隻能通路單個數組元素,其一般形式是:

數組名[下标].成員名

2.對象指針

每一個對象在初始化後都會在記憶體中占有一定的空間。是以,既可以通過對象名通路一個對象,也可以通過對象位址來通路一個對象。對象指針就是用于存放對象位址的變量。聲明對象指針的一般文法形式為:

類名 * 對象指針名;

(1). 用指針通路單個對象成員

一般情況下,用點運算符“.”來通路對象成員,當用指向對象的指針來通路對象成員時,就要用“->”操作符。

(2). 用對象指針通路對象數組

對象指針不僅能引用單個對象,也能通路對象數組。

3.this指針

(1)C++為成員函數提供一個名字為this的指針,這個指針稱為自引用指針。每當建立一個對象時,系統就把this指針初始化為指向該對象,即this指針的值是目前調用成員函數的對象的起始位址。

(2)this指針是隐式使用的,它是作為參數被傳遞給成員函數的。

四、string類

在C++的标準庫中,聲明了一種字元串類型,即字元串類string,類string提供了對字元串進行處理所需的操作。

使用string類必須在程式的開始包括頭檔案string,即要有如下語句:

#include< string >

string類的字元串對象必須先定義才可以使用。其定義格式如下:

string 對象1,對象2,……;

五、向函數傳遞對象

1.使用對象作為函數參數

在向函數傳遞對象時,是通過“傳值調用”傳遞給函數的,即單向傳遞,隻由實參傳給形參,而不能由形參傳回來給實參。是以函數中對對象的任何修改均不影響調用該函數的對象(實參)本身。

2.使用對象指針作為函數參數

對象的指針可以作為函數的參數,使用對象指針作為函數參數可以實作“傳址調用”,即在函數調用時使實參對象和形參對象指針變量指向同一記憶體位址,在函數調用過程中,對形參對象指針所指對象值得改變也同樣影響着實參對象的值。

當函數的形參是對象指針時,調用函數的對應實參應該是某個對象的位址值。

3.使用對象引用作為函數參數

使用對象引用作為函數參數不但具有對象指針用作函數參數的優點,而且用對象引用作函數參數将更簡單、更直接。
c++

繼續閱讀