六個默認成員函式
- 前言
- 建構式
- 概念
- 特性
- 解構式
- 概念
- 特性
- 拷貝建構式
- 概念
- 特性
- 深拷貝相關
- 賦值運算子多載
- 運算子多載
- 賦值運算子多載
- 可多載運算子/不可多載運算子
- const成員
- const修飾類的成員函式
- 取地址及const取地址運算子多載
前言

- 我們先定義一個類
class A
{
};
- 經過編譯器處理后,A不再是空類,會自動生成六個默認的成員函式(這些函式即使我們沒有定義,也會顯示呼叫),生成如下
class A
{
public:
A();//建構式
~A();//解構式
A(const A& a);//拷貝建構式
A& operator=(const A& a);//賦值運算子多載
A* operator &();//取地址運算子多載
const A* operator &() const;//const修飾的取地址運算子多載
};
建構式
概念
- 建構式是一個特殊的成員函式,名字與類名相同,創建型別別物件時由編譯器自動呼叫,保證每個資料成員 都有 一個合適的初始值,并且在物件的生命周期內只呼叫一次

特性
- 建構式是特殊的成員函式,需要注意的是,建構式的雖然名稱叫構造,但是需要注意的是建構式的主要任務并不是開空間創建物件,而是初始化物件
- 特征如下:
- 1.函式名與類名相同
- 2.無回傳值
- 3.物件實體化時編譯器自動呼叫對應的建構式
- 4.建構式可以
多載
class Date
{
public :
// 1.無參建構式
Date ()
{}
// 2.帶參建構式
Date (int year, int month , int day )
{
_year = year ;
_month = month ;
_day = day ;
}
private :
int _year ;
int _month ;
int _day ;
};
void TestDate()
{
Date d1; // 呼叫無參建構式
Date d2 (2015, 1, 1);//呼叫帶參的建構式
// 注意:如果通過無參建構式創建物件時,物件后面不用跟括號,否則就成了函式宣告
// 以下代碼的函式:宣告了d3函式,該函式無參,回傳一個日期型別的物件
Date d3();
}
- 5.如果類中沒有顯式定義建構式,則C++編譯器會自動生成一個無參的默認建構式,一旦用戶顯式定義編譯器將不再生成
class Date
{
public:
/*
// 如果用戶顯式定義了建構式,編譯器將不再生成
Date (int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
*/ private:
int _year; int _month; int _day;
};
void Test()
{
// 沒有定義建構式,物件也可以創建成功,因此此處呼叫的是編譯器生成的默認建構式
Date d;
}
- 6.無參的建構式和全預設的建構式都稱為默認建構式,并且默認建構式只能有一個,注意:
無參建構式、全預設建構式、我們沒寫編譯器默認生成的建構式,都可以認為是默認成員函式
// 默認建構式
class Date
{
public:
Date()
{
_year = 1900 ;
_month = 1 ;
_day = 1;
}
Date (int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
private :
int _year ;
int _month ;
int _day ;
}
解構式
概念
- 建構式功能相反,解構式不是完成物件的銷毀,區域物件銷毀作業是由編譯器完成的,而物件在銷毀時會
自動呼叫解構式,完成類的一些資源清理作業,我們可以把它類比成清道夫的職責,
特性
- 1.解構式是要在類名前加上~
- 2.無引數無回傳值
- 3.一個類有且只有一個解構式,若未顯式定義,系統會自動生成默認的解構式
- 4.物件生命周期結束時,C++編譯系統系統自動呼叫解構式,代碼如下
typedef int DataType;
class SeqList
{
public :
SeqList (int capacity = 10)
{
_pData = (DataType*)malloc(capacity * sizeof(DataType));
assert(_pData);
_size = 0;
_capacity = capacity;
}
~SeqList()//解構式
{
if (_pData)
{
free(_pData ); // 釋放堆上的空間
_pData = NULL; // 將指標置為空
_capacity = 0;
_size = 0;
}
}
private :
int* _pData ;
size_t _size;
size_t _capacity;
};
- 5.關于編譯器自動生成的解構式,是否會完成一些事情呢?下面的程式我們會看到,編譯器生成的默認解構式,對會自定型別成員呼叫它的解構式,我們看如下代碼
class String
{
public:
String(const char* str = "jack")
{
_str = (char*)malloc(strlen(str) + 1);
strcpy(_str, str);
}
~String()
{
cout << "~String()" << endl;
free(_str);
}
private:
char* _str;
};
class Person
{
private:
String _name;
int _age;
};
int main()
{
Person p;
return 0; }
拷貝建構式
概念
- 拷貝建構式是一種特殊的建構式,只有單個形參,該形參是對本型別別物件的參考(一般常用const修飾),在用已存在的型別別物件創建新物件時由編譯器自動呼叫
特性
- 1.拷貝建構式是建構式的一個多載形式
- 2.拷貝建構式的引數只有一個且必須使用參考傳參,使用傳值方式會引發無窮遞回呼叫
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
//拷貝建構式
Date(const Date& d) //必須參考傳參
{
year = d._year;
_month = d._month;
_day = d._day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
Date d2(d1);
return 0; }
- 我們來看一下呼叫的程序

- 3.若未顯示定義,系統生成默認的拷貝建構式, 默認的拷貝建構式物件按記憶體存盤按位元組序完成拷貝,這種拷貝我們叫做 淺拷貝
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
Date d1;
// 這里d2呼叫的默認拷貝構造完成拷貝,d2和d1的值也是一樣的,
Date d2(d1);
return 0;
}
深拷貝相關
- 剛剛的日期類就不需要自己寫拷貝構造,默認生成就可以完成拷貝,但是我們拿一個堆疊類試一下

賦值運算子多載
運算子多載
C++為了增強代碼的可讀性引入了運算子多載,運算子多載是具有特殊函式名的函式,也具有其回傳值型別,函式名字以及引數串列,其回傳值型別與引數串列與普通的函式類似,
函式名字為:關鍵字operator后面接需要多載的運算子符號,
函式原型:回傳值型別 operator運算子(引數串列)
幾個需要注意的點:
- 不能通過連接其他符號來創建新的運算子:比如operator@
- 多載運算子必須有一個型別別或者列舉型別的運算元
- 用于內置型別的運算子,其含義不能改變,例如:內置的整型+,不 能改變其含義
- 作為類成員的多載函式時,其形參看起來比運算元數目少1成員函式的運算子有一個默認的形參this,限定為第一個形參
賦值運算子多載
class Date
{
public :
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
Date (const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
Date& operator=(const Date& d)
{
if(this != &d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
}
private:
int _year ;
int _month ;
int _day ;
};
幾個需要注意的點:
- 引數型別
- 回傳值
- 檢測是否自己給自己賦值
- 回傳*this
- 一個類如果沒有顯式定義賦值運算子多載,編譯器也會生成一個,完成物件按位元組序的值拷貝
可多載運算子/不可多載運算子


const成員
const修飾類的成員函式

-
將const修飾的類成員函式稱之為const成員函式,const修飾類成員函式,實際修飾該成員函式隱含的this指標,表明在該成員函式中不能對類的任何成員進行修改,
-
這里有如下四個問題

取地址及const取地址運算子多載
- 這兩個默認成員函式一般不用重新定義 ,編譯器默認會生成
class Date
{
public :
Date* operator&()
{
return this ;
}
const Date* operator&()const
{
return this ;
}
private :
int _year ; // 年
int _month ; // 月
int _day ; // 日
};
這兩個運算子一般不需要多載,使用編譯器生成的默認取地址的多載即可,只有特殊情況,才需要多載,比如想讓別人獲取到指定的內容,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/267413.html
標籤:其他
上一篇:《Unity Shader入門精要》學習筆記第五章 開始Unity Shader學習之旅
下一篇:AcWing 104. 貨倉選址

