>[info]# **構造函數的需要性**
* 需要有一個專門的函數完成對象的初始化工作,由于類的封裝性,該工作自然落在類的**成員函數**(構造函數)身上.
* 以**類名作為函數名的函數**稱為類的構造函數(C++標準中認為**構造函數是無名函數**,原因是類型名不能作為函數名.這里為了便于理解,將類名稱為構造函數的函數名).
* **聲明構造函數原型**的一般形式: 類名(形參列表);
* **定義構造函數**的一般形式:
~~~
類名::類名(形參列表)<:成員初始化列表> ? //多用于繼承和聚集類
{
語句序列
}
~~~
>[info]# **構造函數作用**
* 知道編譯器為當前命名的對象分配命名空間
* 獨立完成當前類中數據成員的初始化工作
## **例子**
~~~
#include <iostream>
using namespace std;
class Time
{
public:
? Time( ) ? ? //定義構造成員函數,函數名與類名相同
? {
? hour=0; //利用構造函數對對象中的數據成員賦初值
? ? ? ? ? minute=0;
? ? ? ? ? sec=0;
? ? ? }
? ? ? void set_time( ); ? ? ? ? ? //公有成員函數聲明
? ? ? void show_time( ); ? ? ? //公有成員函數聲明
? private:
? ? ? int hour; ? ? ? ? ? ? ? ? //私有數據成員
? ? ? int minute;
? ? ? int sec;
};
?
void Time∷set_time( ) //定義成員函數,向數據成員賦值
{
cin>>hour;
? cin>>minute;
? cin>>sec;
}
?
void Time∷show_time( ) ? ? ? ? //定義成員函數,輸出數據成員的值
{
cout<<hour<<″:″<<minute
? <<″:″<<sec<<endl;
}
?
int main( )
{
Time t1; ? ? ? ? ? ? ? ? ? //建立對象t1,同時調用構造函數t1.Time( )
? t1.set_time( ); ? ? ? ? ? ? //對t1的數據成員賦值
? t1.show_time( ); ? ? ? ? ? //顯示t1的數據成員的值
? Time t2; ? ? ? ? ? ? ? //建立對象t2,同時調用構造函數t2.Time( )
? t2.show_time( ); ? ? ? ? ? //顯示t2的數據成員的值
? return 0;
}
~~~
構造函數也可以在類外定義
~~~
/*在類內進行聲明
在類外定義 */
?
Time::Time() ? //一定要加上類名Time和域限定符::
{
hour=0;
? minute=0;
? sec=0;
}
~~~
>[info]# **帶參的構造函數**
可以采用帶參的構造函數,在調用不同的對象的構造函數時,從外面將不同的數據賦給構造函數,以實現不同的初始化。
定義帶參構造函數的格式:
~~~
構造函數名(類型1,類型2...)
~~~
定義對象時格式:
~~~
類名 對象名(實參1,實參2...);
~~~
## **例子**
~~~
#include <iostream>
using namespace std;
?
class Box
{
public:
? Box(int,int,int); ? ? ? //聲明帶參數的構造函數
? ? ? int volume( ); ? ? ? ? ? //聲明計算體積的函數
? private:
? int height;
? int width; ? ? ?
? int length;
};
?
Box∷Box(int h,int w,int len) ? ? //在類外定義帶參數的構造函數
{
height=h;
? width=w;
? length=len;
}
?
int Box∷volume( ) ? ? ? ? ? //定義計算體積的函數
{
return(height*width*length);
}
?
int main( )
{
Box box1(12,25,30); ? ? ? ? //建立對象box1,并指定box1長,寬,高的值
? cout<<″The volume of box1 is ″
? <<box1.volume( )<<endl;
? Box box2(15,30,21); ? ? ? ? ? //建立對象box2,并指定box2長,寬,高的值
? cout<<″The volume of box2 is ″
? <<box2.volume( )<<endl;
? return 0;
}
~~~
~~~
/* ? 用參數初始化列表對數據成員初始化 ? */
#include <iostream>
#include <cstring>
using namespace std;
?
class Student
{
public:
? Student(char* pName)
? ? ? {
? ? ? cout <<"constructing student " <<pName ? //帶參構造函數或稱有參構造函數
? ? ? ? ? <<endl;
? ? ? ? ? strcpy(name,pName); ? ? ? ?
? ? ? ? ? name[sizeof(name)-1]='\0'; ? ? ? ? ? ? //name[19]='\0' ? ? ? ? ? ? ?
? ? ? }
? ~Student() ? //析構函數
? ? ? {
? ? ? cout <<"destructing " <<name <<endl;
? ? ? }//其他公共成員
? protected:
? char name[20];
};
?
int main()
{
Student ss("Jenny"); /* 調用有參構造函數進行對象的初始化,此句還可寫成:Student ss="Jenny";
? ? ? ? ? ? ? ? ? ? ? ? ? ? 類似的,在ISO C++標準14882中,int a=10;與int a(10);等價.(賦值時只有 ? ? ? ? ? ? ? ? ? ? ? ? ? ? 一種形式,即int a=10) ? */
? return 0;
}
~~~
~~~
/* ? ? 帶多個參數的有參構造函數. ? ? ? */
#include <iostream>
#include <cstring>
?
class Student{
public:
Student(char* pName, int xHours, float xgpa)
? {
? cout <<"constructing student "
? ? ? <<pName <<endl;
? ? ? strncpy(name,pName,sizeof(name));
? ? ? name[sizeof(name)-1]='\0';
? ? ? semesHours=xHours;
? ? ? gpa=xgpa;
? }
? ~Student() //析構函數
? {
? cout <<"destructing " <<name <<endl;
? }//其他公共成員
protected:
char name[20];
? int semesHours;
float gpa;
};
?
int main()
{
Student ss("Jenny",22,3.5);
? return 0;
}
~~~
=
~~~
/* ? ? ? ? 構造函數的重載 ? ? ? ? */
#include <iostream>
using namespace std;
?
class Tdate
{
public:
? Tdate(); ? ? //無參構造函數 稱為默認構造函數
? Tdate(int d);
? ? ? Tdate(int m,int d);
? ? ? Tdate(int m,int d,int y); //4個構造函數 其他公共成員
? protected:
? int month;
? ? ? int day;
? ? ? int year;
};
?
Tdate::Tdate()
{
month=4;
day=15;
? year=1995;
? cout <<month <<"/" <<day <<"/" <<year <<endl;
}
?
Tdate::Tdate(int d)
{
month=4;
day=d;
? year=1996;
? cout <<month <<"/" <<day <<"/" <<year <<endl;
}
?
Tdate::Tdate(int m,int d)
{
month=m;
? day=d;
? year=1997;
? cout <<month <<"/" <<day <<"/" <<year <<endl;
}
?
Tdate::Tdate(int m,int d,int y)
{
month=m;
day=d;
year=y;
? cout <<month <<"/" <<day <<"/" <<year <<endl;
}
?
int main()
{
Tdate aday; ? ? ? //此處不能寫成Tdate aday();
? ? ? ? ? ? ? ? //因為c++編譯器會理解為一個無參函數aday的聲明,該函數返回Tdate類對象.
? Tdate bday(10);
? Tdate cday(2,12);
? Tdate dday(1,2,1998);
? return 0;
}
~~~
~~~
/* ? ? 定義兩個構造函數,其中一個無參數,一個有參數. ? ? ? ? ? */
#include <iostream>
using namespace std;
?
class Box
{
public:
? Box( ); ? ? ? ? ? ? ? ? ? ? ? ? //聲明一個無參的構造函數
? ? ? Box(int h,int w,int len) \
? ? ? ? ? :height(h),width(w),length(len){ } ? ? ? //聲明一個有參的構造函數,用參數的初始化表
? ? ? //對數據成員初始化
? ? ? int volume( );
? private:
? ? ? int height;
? ? ? int width;
? ? ? int length;
};
?
Box∷Box( ) ? ? ? ? ? //定義一個無參的構造函數
{
height=10;
? width=10;
? length=10;
}
?
int Box∷volume( )
{
return(height*width*length);
}
?
int main( )
{
Box box1; ? ? ? ? ? ? //建立對象box1,不指定實參
? cout<<″The volume of box1 is ″<<box1.volume( )<<endl;
? Box box2(15,30,25); ? //建立對象box2,指定3個實參
? cout<<″The volume of box2 is ″<<box2.volume( )<<endl;
? return 0;
}
~~~
**“\\”的作用**:
* 普通的\\
* 轉義字符
* 續行,上下兩行屬于同一行語句. ' \ '后不能寫任何東西
~~~
/* ? ? 默認構造函數(缺省構造函數) ? ? ? */
#include <iostream>
#include <cstring>
using namespace std;
class Student
{
public:
? Student(char* pName)
? {
? strncpy(name,pName,sizeof(name));
? ? ? name[sizeof(name)-1]='\0';
? }
? Student(){}
protected:
? char name[20];
};
?
int main()
{
Student noName; ? ? ? ? //ok 調用無參構造函數
? Student ss("Jenny"); ? ? //ok 調用有參構造函數
? return 0;
}
/* 若要創建無參對象,即使在類中已有有
? 參構造函數的情況下,也要增加一個無
? 參構造函數,否則編譯出錯.
*/
~~~
>[info]# **規定**
* 構造函數的**調用時機**對理解C++程序的執行過程非常重要。
* c+規定,在創建一個對象時,構造函數被系統**自動調用**。這就意味著當執行一個對象聲明語句或者用操作符new動態創建對象時,都會導致自動調用執行構造函數除此之外,在程序中不能直接調用構造函數,因為c++標準中認為構造函數是無名函數,而無名函數對于程序正文而言是不可見的.
<br>
## **c++規定:**
* 不能為構造函數指定任何返回類型,即使void也不行
* 構造函數允許帶參,因此構造函數可以重載。構造函數可以分為無參和有參構造函數。無參構造函數又稱為**缺省構造函數**或**默認構造函數**
* 如果**沒有為一個類定義任何構造函數**時,編譯器會為該類**自動產生**一個隱含聲明的**缺省構造函數**。隱含聲明的缺省構造函數什么都不做
* 構造函數可以是類的**public**的或者**protected**的成員函數,當構造函數為**protected**的構造函數時,意味著除自身之外只有其**派生類**和**友員**能夠創建該類的對象。
- 介紹
- 編程設計語言
- 第一章 對C++的初步認識
- 1.2 最簡單的C++程序
- 1.3 C++對C的補充
- 1.3.1 return
- 1.3.2 輸入輸出流
- 1.3.3 putchar 和 getchar
- 1.3.4 用const定義常變量
- 1.3.5 函數原型聲明
- 1.3.6 內置函數
- 1.3.7 函數重載
- 1.3.8 函數模板
- 1.3.9 有默認值的參數
- 1.3.10 作用域
- 1.3.11 const修飾指針
- 1.3.12 引用
- 1.3.13 生命期
- 1.3.14 變量
- 1.3.15 字符串變量
- 第二章 類與對象
- 2.2 類的聲明和對象的定義
- 2.3 類的成員函數
- 第三章 關于類和對象的進一步討論
- 3.1 構造函數
- 3.1.1 對象的初始化
- 3.1.2 構造函數
- 3.2 析構函數
- 3.3調用析構函數和構造函數的順序
- 3.4 對象數組
- 3.5 對象指針
- 3.6 共享數據的保護
- 3.7 對象的建立與釋放
- 3.8 對象的賦值與復制
- 3.9 靜態成員
- 3.10 友元
- 3.11 類模板
- 第四章 運算符重載
- 數據類型轉換
- 運算符重載
- 重載流插入運算符和流提取運算符
- 第五章 繼承與派生
- 繼承與派生
- 第六章 多態性與虛函數
- 多態性
- 虛函數
- 純虛函數與抽象類