1. 程式人生 > 程式設計 >C++語法詳解之封裝、建構函式、解構函式

C++語法詳解之封裝、建構函式、解構函式

大家先了解下什麼是建構函式,什麼是解構函式,作用是什麼?

建構函式(方法)是物件建立完成後第一個被物件自動呼叫的方法。它存在於每個宣告的類中,是一個特殊的成員方法。作用是執行一些初始化的任務。Php中使用__construct()宣告構造方法,並且只能宣告一個。

解構函式(方法)作用和構造方法正好相反,是物件被銷燬之前最後一個被物件自動呼叫的方法。是PHP5中新新增的內容作用是用於實現在銷燬一個物件之前執行一些特定的操作,諸如關閉檔案和釋放記憶體等。

下面在通過具體例子看下C++語法詳解之封裝、建構函式、解構函式。

成員變數私有化,提供公共的getter和setter給外界去訪問成員變數

class Person {
 int age;
 
public:
 void setAge(int age){
  this->age = age;
 }
 
 int getAge(){
  return this->age;
 }
 
};

int main(){
 Person person;
 person.setAge(10);
 cout << person.getAge() << endl;
}

堆空間

在程式執行過程,為了能夠自由控制記憶體的生命週期、大小,會經常使用堆空間的記憶體

堆空間的申請\釋放

malloc \free
new \delete
new [] \delete []

注意

  • 申請堆空間成功後,會返回那一段記憶體空間的地址
  • 申請和釋放必須是1對1的關係,不然可能會存在記憶體洩露

現在的很多高階程式語言不需要開發人員去管理記憶體(比如Java),遮蔽了很多記憶體細節,利弊同時存在

  • 利:提高開發效率,避免記憶體使用不當或洩露
  • 弊:不利於開發人員瞭解本質,永遠停留在API呼叫和表層語法糖,對效能優化無從下手

例如開盤int型別的空間,使用完之後銷燬

int *p = (int *)malloc(sizeof(int));
 *p = 10;
 free(p);
 
 int *p2 = new int;
 *p2 = 20;
 delete p2;
 
 int *p3 = new int[3];
 *p = 10;
 *(p+1) = 20;
 *(p+2) = 30;
 delete [] (p3);

堆空間的初始化

memset

memset 函式是將較大的資料結構(比如物件、陣列等)記憶體清零的比較快的方法

如下所示

 Person person;
 person.age = 10;
 person.height = 199;
 //從person的地址開始,每個位元組都賦值為0
memset(&person,sizeof(person));

初始化

int *p1 = (int *)malloc(sizeof(int)); //*p1 未初始化
int *p2 = (int *)malloc(sizeof(int));
memset(p2,sizeof(int));//將 *p2 的每一個位元組都初始化為0

如下幾種方式

int *p1 = new int;   //未初始化
int *p2 = new int();   //被初始化為0
int *p3 = new int(5);  //被初始化為5
int *p4 = new int[3];  //陣列元素未被初始化
int *p5 = new int[3]();  //3個數組元素都被初始化0
int *p6 = new int[3]{};  //3個數組元素都被初始化0
int *p7 = new int[3]{5};  //陣列首元素被初始化為5,其他元素被初始化為0

建構函式(Constructor)

建構函式(也叫構造器),在物件建立的時候自動呼叫,一般用於完成物件的初始化工作

特點

  • 函式名與類同名,無返回值(void都不能寫),可以有引數,可以過載,可以有多個建構函式
  • 一旦自定義了建構函式,必須用其中一個自定義的建構函式來初始化物件

注意

通過malloc分配的物件不會呼叫建構函式
一個廣為流傳的、很多教程\書籍都推崇的錯誤結論:
預設情況下,編譯器會為每一個類生成空的無參的建構函式
正確理解:在某些特定的情況下,編譯器才會為類生成空的無參的建構函式
比如我們自己寫2個建構函式

class Person{
public:
 int age;
 
 Person(){
  cout << "Person()" << endl;
 }
 
 Person(int age){
   cout << "Person(int age))" << endl;
 }
};

在不同的空間呼叫的時候,如下區別

// 全域性區
Person p1;  //呼叫Person()
Person p2(); //這是一個函式,函式名是p2,返回值型別是Person,無參
Person p3(18); //呼叫 Person(int)

int main(){
 //棧空間
 Person p4;  //呼叫Person()
 Person p5(); //這是一個函式,函式名是p5,返回值型別是Person,無參
 Person p6(18); //呼叫 Person(int)
 
 
 //堆空間
 Person *p7 = new Person;  //呼叫Person()
 Person *p8 = new Person(); //呼叫Person()
 Person *p9 = new Person(20); //呼叫 Person(int)
}

解構函式

解構函式(也叫析構器),在物件銷燬的時候自動呼叫,一般用於完成物件的清理工作

特點

函式名以~開頭,與類同名,無返回值(void都不能寫),無參,不可以過載,有且只有一個解構函式

注意

  • 通過malloc分配的物件free的時候不會呼叫解構函式
  • 建構函式、解構函式要宣告為public,才能被外界正常使用

例如下面的程式碼

class Cat{
public:
 int age;
 Cat(){
  cout << "Cat()" << endl;
 }
 
 ~Cat(){
  cout << "~Cat()" << endl;
 }
};


class Person{
public:
 int age;
 Cat *cat;
 Person(){
  this->cat = new Cat();
  cout << "Person()" << endl;
 }
 
 ~Person(){
  cout << "~Person()" << endl;
 }
};

int main(){
 {
  Person person;
 }
 return 0;
}

輸出

Cat()
Person()
~Person()

當person銷燬的時候,其持有的cat並沒有銷燬。

原因

當person銷燬的時候,其指向cat物件的指標銷燬了,但是堆空間的cat物件依然存在,就會有記憶體洩露。所以需要在解構函式裡面來釋放掉。類似的解構函式在許多其他語言底層也是應用廣泛,例如Objective-C的原始碼中,大量使用解構函式。

程式碼改成如下所示:

~Person(){
  delete cat;
  cout << "~Person()" << endl;
 }

輸出

Cat()
Person()
~Cat()
~Person()

可知,cat物件才真正銷燬。

總結

到此這篇關於C++語法詳解之封裝、建構函式、解構函式的文章就介紹到這了,更多相關c++ 封裝建構函式解構函式內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!