一、構造函數
1、構造函數定義
構造函數函數名與類名相同,無返回值類型(void也不可以),在創建對象時自動執行。
#include <iostream>
using namespace std;
class Person{
private:
char *m_name;
int m_age;
public:
//聲明構造函數
Person(char *name, int age);
//聲明普通成員函數
void show();
};
//定義構造函數
Person::Person(){
m_name="小孔";
m_age =20;
}
Person::Person(char *name, int age){
m_name = name;
m_age = age;
}
//定義普通成員函數
void Person::show(){
cout<<m_name<<"\t"<<m_age<<"\t"<<endl;
}
int main(){
//創建對象時向構造函數傳參,調用帶參構造
Person p1("小劉", 15);
p1.show();
//創建對象時向構造函數傳參
Person *p2 = new Person("小王", 16);
p2 -> show();
//調用無參構造
Person p3;
p3.show();
return 0;
}
構造函數應爲共有屬性,否則在創建對象時就無法調用該構造函數。
構造函數的作用是給類中的成員賦值,調用該構造函數,只需要在創建對象的同時傳參賦值,就像上例創建的對象p1,p2.只不過在棧上創建對象時,實參位於對象名後面,在堆上創建對象時,實參位於類名後面。
2、函數重載
構造函數是可以重載的,就像上例中的構造函數重載,一個該有形參,一個沒有形參。
構造函數的調用是強制性的,**一旦在類中定義了構造函數,那麼創建對象時就一定要調用,不調用是錯誤的。**如果有多個重載的構造函數,那麼創建對象時提供的實參必須和其中的一個構造函數匹配,這也就意味着,創建對象時只有一個構造函數會被調用。
在調用帶形參的函數時,需要在創建對象時,傳遞實參;而在調用沒有參數的構造時,可以直接創建對象,並且不用加(),這就表示調用的是不帶參數的構造。
3、默認構造函數
在c++類中會存在着一個默認構造函數,如果程序員在類的成員中沒有編寫構造函數,那麼系統會自動生成空的構造函數體,儘管這個函數不執行任何操作。
一個類必須有構造函數,要麼用戶自己定義,要麼編譯器自動生成。
如果用戶自己定義了構造函數,那麼編譯器便不再自動生成構造函數。
4、構造函數初始化列表
#include <iostream>
using namespace std;
class Person{
private:
char *m_name;
int m_age;
public:
Person(char *name, int age);
void show();
};
//採用初始化列表
Person::Person(char *name, int age): m_name(name), m_age(age) {
}
void Person::show(){
cout<<m_name<<m_age<<endl;
}
int main(){
Person p1("小王", 15);
p1.show();
Person *p2 = new Person("小美",16);
p2 -> show();
return 0;
}
初始化列表的作用是對類內的成員變量進行初始化,寫法如上例,是在函數首部與函數體之間添加了一個冒號:
,隨後用類內成員(形參)
的寫法,表示將形參值傳遞給該類內成員。初始化列表可以用於全部成員變量,也可以只用於部分成員變量,用於部分成員變量時,只需要在:
後,寫出所要初始化的變量即可。
成員變量的初始化順序與初始化列表中列出的變量的順序無關,它只與成員變量在類中聲明的順序有關。
初始化列表還有一個作用是給const成員變量賦值,初始化 const 成員變量的唯一方法就是使用初始化列表。
二、 析構函數
創建對象時系統會自動調用構造函數進行初始化工作,同樣,銷燬對象時系統也會自動調用一個函數來進行清理工作,這個函數就是析構函數。
#include<iostream>
using namespace std;
class student
{
private:
int m_a;
int m_b;
public:
student(int a,int b);
~student();
};
student::student(int a, int b): m_a(a), m_b(b){}
student::~student()
{
cout << m_a << "\t" << m_b << endl;
}
int main()
{
student stu(1,2);
system("pause");
return 0;
}
上例可見析構函數的形式:~類名(){}
析構函數沒有參數,不能被重載,一個類只能有一個析構函數。如果用戶沒有定義,編譯器會自動生成一個默認的析構函數。
析構函數的調用條件:
在所有函數之外創建的對象是全局對象,它和全局變量類似,位於內存分區中的全局數據區,程序在整體結束執行時會調用這些對象的析構函數。
在棧區系統開闢的內存,系統會自動釋放並調用析構函數。
在堆區手動開闢的內存,手動delete釋放時,纔會調用析構函數