四、實驗結論
- 驗證性實驗部分
總結你對類、對象、構造函數、復制構造函數、析構函數的認識、理解和思考。
類與對象:


對象是對客觀事物的抽象,類是對對象的抽象。
(1)類類型的聲明:
class 類名
{
public:
公用的數據和成員函數
protected:
保護的數據和成員函數
private:
私有的數據和成員函數
}
(2)什么是構造函數?
通俗的講,在類中,函數名和類名相同的函數稱為構造函數。它的作用是在建立一個對象時,作某些初始化的工作(例如對數據賦予初值)。C++允許同名函數,也就允許在一個類中有多個構造函數。如果一個都沒有,編譯器將為該類產生一個默認的構造函數。此默認構造函數的功能是為對象分配內存,但無法為成員數據賦初值。 構造函數上惟一的語法限制是它不能指定返回類型,甚至void 也不行。
用於在創建對象時為對象分配內存 ,並可以將其初始化到特定的狀態。
1,不帶參數的構造函數:一般形式為: 類名 對象名(){函數體}
2,帶參數的構造函數:不帶參數的構造函數,只能以固定不變的值初始化對象。帶參數構造函數的初始化要靈活的多,通過傳遞給構造函數的參數,可以賦予對象不同的初始值。
一般形式為:構造函數名(形參表); 創建對象使用時:類名 對象名(實參表);
如果類中沒有寫構造函數,編譯器會自動生成一個隱含的默認構造函數,該函數是個空值。
小結: 構造函數的重載
構造函數用於在創建對象時為對象分配內存 ,並可以將其初始化到特定的狀態,是特殊的成員函數。
與普通函數類似,構造函數也可以被重載。
① 在一個類的定義中,可以包含多個構造函數。這些構造函數有相同的函數名稱,但具有不同的形參列表。
② 定義對象時,編譯器會根據參數的個數、類型來決定調用哪一個重載構造函數。
③ 當重載不帶參數的構造函數和帶默認形參值的構造函數時,程序可能會產生二義性。因此,在實際編程中應避免這一情形。
(3)析構函數:
當一個類的對象離開作用域時,析構函數將被調用(系統自動調用)。析構函數的名字和類名一樣,不過要在前面加上 ~ 。對一個類來說,只能允許一個析構函數,析構函數不能有參數,並且也沒有返回值。析構函數的作用是完成一個清理工作,如釋放從堆中分配的內存。
一個類中可以有多個構造函數,但析構函數只能有一個。對象被析構的順序,與其建立時的順序相反,即后構造的對象先析構。
(4)復制構造函數:
① 是特殊的構造函數: 其形參是本類對象的引用
② 復制構造函數在下述情形被調用:
使用已有的對象初始化一個新的對象
復制構造函數有且只有一個形參,而且這個形參必須是本類對象的引用。
在C++中,下面三種對象需要調用拷貝構造函數(有時也稱“復制構造函數”):
- 一個對象作為函數參數,以值傳遞的方式傳入函數體;
- 一個對象作為函數返回值,以值傳遞的方式從函數返回;
- 一個對象用於給另外一個對象進行初始化(常稱為賦值初始化);
如果類中沒有寫復制構造函數,編譯器會自動生成一個隱含的復制構造函數,功能是把初始值對象的每個數據成員的值都復制到新建立的對象中。
通常的原則是:①對於凡是包含動態分配成員或包含指針成員的類都應該提供拷貝構造函數;②在提供拷貝構造函數的同時,還應該考慮重載"="賦值操作符號。
class 類名
{
public:
類名(形參表) ; // 構造函數
類名(類名 &對象名); // 復制構造函數
…
}
類名::類名(類名 &對象名)
{
…
}
ps:用已存在對象初始化該類的另一個對象,兩種方法:1)Clock hisclock(myclock); <復制函數會被調用> 2)Clock hisclock = myclock;<復制函數不被調用>
//4-11.定義並實現一個 矩形類,有長,寬兩個屬性,由成員函數計算矩形的面積//
#include<iostream>
using namespace std;
class Rectangle{ //聲明定義類rectangle及其數據和方法
public: //外部接口
Rectangle(float a,float b); //構造函數<帶有參數a,b--長,寬>
float rectanglearea(); //計算矩形的面積
private: //私有數據成員
float Length,width; //長,寬
};
//類的實現
//構造函數初始化數據成員a,b
Rectangle::Rectangle(float a,float b){
Length=a;
width=b;
}
//計算矩形的面積
float Rectangle::rectanglearea() {
return Length*width;
}
//主函數實現
int main(){
float Length,width;
cout<<"Enter the Length and width of the rectangle:" ; //提示用戶輸入長,寬
cin>>Length>>width;
class Rectangle c(Length,width); //定義的類的對象---矩形c
cout<<"The area of Retangle is:"<<c.rectanglearea()<<endl; //輸出矩形面積
return 0;
}
//定義類的對象時,沒加class就顯示我是錯誤的

//4-20,定義一個負數類Complex,使得下面的代碼能夠工作。
//Complex c1(3,5); ---用復數3+5i初始化c1
//Complex c2=4.5; ---用實數4.5初始化c2
//c1.add(c2); ---將c1與c2相加,結果保存在c1中
//c2.show();---將c1輸出(這時的結果應該是7.5+5i)
#include<iostream>
using namespace std;
class Complex{
public:
Complex(double r0,double i0); //用戶自定義的構造函數<帶有兩個參數>
Complex(double r0); //同上,<帶有一個參數 >
Complex(Complex &c0); //用戶自定義的復制構造函數---形參必須是該類對象的引用
void add(Complex &c0); //同上
void show(){cout<<real<<"+" <<imaginary<<"i"<<endl; } //函數體的實現在類內部,是內聯成員函數
private:
double real;
double imaginary;
};
//類的實現
Complex::Complex(double r0,double i0){
real=r0;
imaginary=i0;
}
Complex::Complex(double r0){ //這兩個可以合並在一起,只用一個構造函數《下面的改成c2(4.5,0)》
real=r0;
imaginary=0;
}
Complex::Complex(Complex &c0){
real=c0.real;
imaginary=c0.imaginary;
}
void Complex::add(Complex &c0){ // 此處聲明會引用到類的對象,實現對象間的運算?不是太理解
real+=c0.real;
imaginary+=c0.imaginary;
}
//主函數的實現
int main()
{
Complex c1(3,5); //定義Complex類的對象c1
Complex c2(4.5); // 定義Complex類的對象c2
c1.add(c2); //進行add運算--c2的值加到c1里面
c1.show(); //執行show函數--以我要求的形式輸出
return 0;
}

1,操作還不是太熟練,2,析構函數只知道擺在類里面 ~類名,但是下面就不知道怎么用它。3,復制構造函數的原理
