面向物件(2)
阿新 • • 發佈:2018-12-20
/* OOP:封裝 繼承 多型 OOP:抽象 封裝 繼承 多型
許可權:public private this:成員方法宣告或者定義的時候加上this指標 成員方法呼叫的時候,自動傳參this指標 在成員方法內使用成員變數的地方,加上this指標的解引用
建構函式: 初始化物件時候自動呼叫的成員方法 如果不自己實現建構函式,編譯器會預設生成一個預設建構函式 如果自己實現,則編譯器不會生成了 建構函式可以過載
拷貝構造: 用一個已經存在的物件,構造同類型的新物件 防止淺拷貝 如果不自己實現,預設生成一個淺拷貝的拷貝構造 拷貝建構函式必須傳引用
=: 用一個已經存在的物件給另一個已經存在的物件賦值 如果不自己實現,編譯器會預設生成一個淺拷貝的= 防止自賦值 防止記憶體洩露 防止淺拷貝
析構: 一個物件的生存週期滿,自動呼叫的成員方法 解構函式沒有引數,不可以過載 如果不自己實現,編譯器會預設生成 防止記憶體洩漏
*/
/* 臨時物件 顯式:出現型別名 隱式:未出現型別名
內建型別的臨時物件都是常量
自定義型別產產生的臨時物件:隱式 :常量 顯式:非常量
*/
#include<iostream> #include<assert.h> #include<string.h> using namespace std; class CGoods { public: CGoods(const char *name = NULL, int num = 0, double price = 0.0) { cout << "CGoods(const char *name, int num, double price)" << endl; if (NULL != name) { _name = new char[strlen(name) + 1]; strcpy_s(_name, strlen(name) + 1, name); } else { _name = NULL; } _num = num; _price = price; } CGoods(const CGoods &src) { cout << "CGoods(const CGoods &src)" << endl; //_name = src._name;//error 此為淺拷貝 _name = new char[strlen(src._name) + 1]; strcpy_s(_name, strlen(src._name) + 1, src._name); _num = src._num; _price = src._price; } CGoods &operator=(const CGoods& src) { cout << "CGoods &operator=(const CGoods& src)" << endl; //防止自賦值 if (this == &src) { return *this; } //防止記憶體洩漏 if (_name !=- NULL) delete []_name; //防止淺拷貝 _name = new char[strlen(src._name) + 1]; strcpy_s(_name, strlen(src._name) + 1, src._name); _num = src._num; _price = src._price; return *this; } ~CGoods()//先構造的後析構 { cout << "~CGoods()" << endl; if (NULL != _name) { delete[]_name; _name = NULL; } } void show() { cout << "name:" << _name << endl; cout << "num:" << _num << endl; cout << "price:" << _price << endl; } private: char* _name; int _num; double _price; }; CGoods fun1(CGoods& goods) //傳引用 //fun1(goods5):用goods5拷貝構造goods { //CGoods goods1 = goods; //用goods拷貝構造goods1 //return goods; //用goods拷貝構造臨時量(返回值)臨時量在main函式棧幀上,不會先被析構 //析構的時候先析構goods1 然後是goods 待返回完成後,臨時量要進行析構 緊接著析構goods5 return "jidan"; /* 構造臨時物件 拷貝構造goods6 析構臨時物件 直接構造 */ } int main() { CGoods goods1("mianbao", 20, 1.5);//構造goods1 //CGoods goods2(goods1);//用goods1拷貝構造goods2 //CGoods goods3 = goods2;//用goods2拷貝構造goods3 用已生成的good2構造新生成的goods3 //goods3 = goods1;//賦值 用已生成的goods1給已生成的goods3賦值 //CGoods goods4("xiangchang");//構造goods4 CGoods goods5 = "latiao";//直接構造goods5 /* 先利用char*構造一個臨時物件 (臨時物件為CGood型別) 用臨時物件拷貝構造goods5 //臨時物件的生存週期僅在這一個語句 析構臨時物件 編譯器優化為:直接構造 */ goods5 = "niunai"; /* 1.先構造臨時物件 2.用臨時物件給goods5賦值 3.析構臨時物件 不能優化 */ //const CGoods &gb = "kuangquanshui";//隱式(沒有出現型別名)產生臨時物件 CGoods &ga = (CGoods)"fangbianmian";//顯式產生臨時物件 //char * 強轉為CGood型別 強轉是否成功要看是否有合適的建構函式 /* 1.先構造臨時物件 2.把臨時物件的引用給ga 3.不析構 臨時物件一旦被引用,它的生存週期就和引用相同 */ //const int &a =(int)10;//用10產生一個臨時變數,將臨時變數的地址給引用a //const int &a =(int)10;//顯式產生整型的臨時物件 //int &a = (int)10;//不允許洩露常量的引用或者地址給非常量的引用或者指標 //int &b = 20; CGoods goods6(fun1(goods5));//用funl函式返回值的臨時物件拷貝構造goods6 return 0; }
自定義型別傳參都需要提前開闢空間
在記憶體空間上構造,不能在暫存器上構造