類的三大特性
- 封裝性:將緊密相關的數據和方法組合成類,並對類中的成員訪問進行限制,防止外界對類內部的破壞。
- 繼承性:經過不同程度的抽象,將分散的各種類聯繫起來,從而建立起一個相互聯繫的系統。當系統中添加新類時,不用從頭開始寫程序,只需要從已有的系統中選取相應的基類,繼承它,然後添加新的功能即可。
- 多態性:類定義一個接口可以有不同的實現,只有在類運行時才確定使用哪個實現。
類的定義
class 類名
{
private: //私有
私有數據成員和成員函數;
protected: //保護
保護數據成員和成員函數;
public: //公有
公有數據成員和成員函數;
}
一個類中的成員函數可以不受限制的訪問該類的數據成員,而該類以外的類訪問該類的數據成員和成員函數會受到限制,這體現了類的封裝性。
定義在類體內的成員函數叫內聯函數。定義在類外的成員函數叫外聯函數。我們可以通過關鍵字 inline 將外聯函數轉換成內聯函數(其外聯轉內聯的過程在編譯中進行)。
(一)
class student
{
private:
char name[9];
public:
void showname();
};
void student::showname() //外聯函數
{
cout << name;
}
(二)
class student
{
private:
char name[9];
public:
void showname() //內聯函數
{
cout << name;
}
};
(三)編譯時外聯轉內聯
class student
{
private:
char name[9];
public:
void inline showname(); //編譯時外聯轉內聯
};
void student::showname()
{
cout << name;
}
在使用內聯函數時應該注意:
- 內聯函數體內不能有循環語句和 switch 語句。
- 內聯函數必須在第一次被調用之前定義。
數據成員
爲了體現面向對象程序設計信息的隱蔽性,數據成員均被定義爲私有成員。並且在定義是應該注意一下兩點:
- 數據成員不能在定義時對其進行初始化,其初始化是在具體對象創建後由構造函數完成的。
- 數據成員不能進行遞歸定義,即不能使用自身類的對象作爲該類的數據成員。
class A
{
private:
int i = 1; //錯誤
A i; //錯誤
int i; //正確
}
成員函數
成員函數一般格式爲:
類型 類名::函數名(參數)
{
函數體;
}
“::” 爲作用域運算符,用於聲明成員函數所從屬的類。
成員函數向類的外部給出了提供服務的接口,該接口是對封裝數據成員進行操作的唯一途徑。
成員函數調用方式如下:
int add_init(int x=6,int y=30)
{
return(x+y);
}
add_init(10,20); //用實參來初始化形參,實現10 + 20
add_init(10); //形參x採用實參值10,y採用默認值30,實現10 + 30
add_init(); //x y 都使用默認值,實現 6 + 30
訪問權限
類成員從訪問權限上分:公有(public)、私有(private)、保護(protected)。默認爲 private 。
- 公有(public):任何代碼都可以訪問。
- 私有(private):只能被自身成員函數及友元函數訪問。
- 保護(protected):可以被自身成員函數、友元函數和派生類成員訪問。
構造函數
- 是成員函數,其說明在類體內。其函數體可寫在體內也可寫在體外。
- 名字和類名相同,定義和說明構造函數時,不必指明函數的類型。
- 用於創建對象時系統自動調用,也可在函數中調用構造函數創建無名對象。
- 可以由一個或多個參數,也可以沒有參數。
- 可以重載。
- 在類的定義中沒有給出構造函數,則系統會自動創建一個默認的構造函數,默認構造函數不起任何作用,沒有參數。在創建對象時,將數據成員初始化爲0。
- 不能被繼承,不能說明爲虛函數,不能被顯示調用,不能對構造函數進行取地址操作。
- 是公有成員函數。
class A
{
public:
A()
{
cout<<"AAA\n";
}
};
class B
{
public:
B()
{
cout<<"BBB\n";
}
};
class C
{
public:
C()
{
cout<<"CCC\n";
num = 0;
}
protected:
A a;
B b;
int num;
};
void main()
{
C c;
cout<<"back into main.\n";
}
輸出:
AAA
BBB
CCC
back into main.
主程序運行,當遇到創建C類的對象時,就調用構造函數C()。該構造函數運行時,首先分配空間,包含一個A對象,一個B對象,一個int型數據,然後在類聲明的對象成員依次調用其構造函數。
析構函數
- 是成員函數,其說明在類體內。其函數體可寫在體內也可寫在體外。
- 名字和類名相同,在析構函數前加“~”,表明功能與構造函數相反。
- 它可以被自動調用,也可以被系統調用。
- 通常利用析構函數刪除對象中由指針成員所指向的動態分配到存儲空間,當類中不使用動態存儲空間時,通常不需要定義析構函數。
析構函數的調用方式:
- 一個對象當其結束生命週期時,例如一個函數體內定義的對象,當該函數結束時,自動調用析構函數釋放該對象。
- 使用new運算符創建的對象,在使用delete運算符釋放該對象時,系統自動調用析構函數。
- 當變量超過作用域時,析構函數被隱式調用。
- 當指向對象的指針超過作用域時,析構函數不能被隱式調用:如果要刪除對象時,必須使用delete操作符。
- 對於全局變量,在主函數main()終止時,自動調用析構函數。
- 對於局部變量,當函數結束時,自動調用析構函數。