<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
物件的初始化和清理也是兩個非常重要的安全問題
一個物件或者變數沒有初始狀態,對其使用後果也是未知
同樣的使用完一個物件或變數,沒有及時清理,也會造成一定的安全問題
建構函式語法:類名(){}
1.建構函式,沒有返回值也不寫void
2.函數名稱與類名相同
3.建構函式可以有引數,因此可以發生過載
4.程式在呼叫物件時候會自動呼叫構造,無須手動呼叫,而且只會呼叫一次
解構函式語法:~類名(){}
1.解構函式,沒有返回值也不寫void
2.函數名稱與類名相同,在名稱前加上符號~
3.解構函式不可以有引數,因此不可以發生過載
4.程式在呼叫物件前會自動呼叫解構,無須手動呼叫,而且只會呼叫一次
#include<iostream> using namespace std; //物件的初始化和清理 //1.建構函式 實現初始化的操作 class Person { public: //1建構函式 //沒有返回值 不用寫void //函數名 與類名相同 //建構函式可以有引數,可以發生過載 //建立物件時,建構函式會自動呼叫,而且只呼叫一次 Person() { cout<< "Person建構函式的呼叫" << endl; } //2.解構函式 實現清理的操作 //沒有返回值 不寫void //函數名和類名相同 在名稱前加一個~ //解構函式不可以有引數,不可以發生過載 //物件在銷燬前 會自動呼叫解構函式 而且只會呼叫一次 ~Person() { cout << "Person解構函式的呼叫" << endl; } }; //構造和解構都是必須有的實現,如果我們自己不提供,編譯器會提供一個空實現的構造和解構 void test01() { Person p;//在棧上的資料,test01執行完畢後,釋放這個物件 } int main() { test01(); system("pause"); return 0; }
建構函式的分類以及呼叫
兩種分類方式:
三種呼叫方式:
#include<iostream> using namespace std; //建構函式的分類及呼叫 //分類 //按照引數分類 無參構造(預設構造)和有參構造 //按照型別分類 普通構造 拷貝構造 class Person { public: //建構函式 Person() { cout << "Person的無參建構函式呼叫" << endl; } Person(int a) { age = a; cout << "Person的有參建構函式呼叫" << endl; } //拷貝建構函式 Person(const Person &p) { //將傳入的人身上的所有屬性,拷貝到「我」身上 age = p.age; cout << "Person的拷貝建構函式呼叫" << endl; } ~Person() { cout << "Person的解構函式呼叫" << endl; } int age; }; //呼叫 void test01() { //1.括號法 //Person p1;//預設函數呼叫 //Person p2(10);//有參建構函式 //Person p3(p2);//拷貝建構函式 //注意事項 //呼叫預設建構函式的時候,不要加() //因為下面這行程式碼,編譯器會認為是一個函數的宣告,不會認為在建立物件 //Person p1(); /*cout << "p2的年齡:" << p2.age << endl; cout << "p3的年齡:" << p3.age << endl;*/ //2.顯示法 //Person p1; //Person p2 = Person(10);//有參構造 //Person p3 = Person(p3);//拷貝構造 //Person(10);//匿名物件 特點:當前行執行結束後,系統會立即回收掉匿名物件 // // 注意事項2 // 不要利用拷貝建構函式,初始化匿名物件 編譯器會認為Person(p3) === Person p3;物件宣告 //Person(p3); //3.隱式轉換法 Person p4 = 10;//相當於 寫了 Person p4 = Person(10); 有參構造 Person p5 = p4;//拷貝構造 } int main() { test01(); system("pause"); return 0; }
拷貝建構函式呼叫時機通常有三種情況
1.使用一個已經建立完畢的物件來初始化一個新物件
2.值傳遞的方式給函數引數傳值
3.以值方式返回區域性物件
#include<iostream> using namespace std; //拷貝建構函式的呼叫時機 //1.使用一個已經建立完畢的物件來初始化一個新物件 //2.值傳遞的方式給函數引數傳值 //3.值方式返回區域性物件 class Person { public: Person() { cout << "Person的預設建構函式呼叫" << endl; } Person(int age) { cout << "Person的有參建構函式呼叫" << endl; m_Age = age; } Person(const Person &p) { cout << "Person的拷貝建構函式呼叫" << endl; m_Age = p.m_Age; } ~Person() { cout << "Person解構函式呼叫" << endl; } int m_Age; }; //拷貝建構函式的呼叫時機 //1.使用一個已經建立完畢的物件來初始化一個新物件 void test01() { Person p1(20); Person p2(p1); cout << "p2的年齡為:" << p2.m_Age << endl; } //2.值傳遞的方式給函數引數傳值 void doWork(Person p) { } void test02() { Person p; doWork(p); } //3.值方式返回區域性物件 Person doWork2() { Person p1; return p1; } void test03() { Person p = doWork2(); } int main() { //test01(); //test02(); test03(); system("pause"); return 0; }
預設情況下,c++編譯器至少給一個類新增3個函數
1.預設建構函式(無參,函數體為空)
2.預設解構函式(無參,函數體為空)
3.預設拷貝建構函式,對屬性進行值拷貝
建構函式呼叫規則如下
如果使用者定義有參建構函式,c++不再提供預設無參構造,但是會提供預設拷貝構造
如果使用者定義拷貝建構函式,c++不再提供其他建構函式
#include<iostream> using namespace std; //建構函式的呼叫規則 //1.建立了一個類,c++編譯器會給每個類都新增至少三個函數 //預設構造 (空實現) //解構函式 (空實現) //拷貝構造 (值拷貝) //2.如果我們寫了有參建構函式,編譯器就不再提供預設構造,依然提供拷貝構造 //如果我們寫了拷貝建構函式,編譯器不再提供其他建構函式了 class Person { public: /*Person() { cout << "Person的預設建構函式呼叫" << endl; }*/ /*Person(int age) { cout << "Person的有參建構函式呼叫" << endl; m_Age = age; }*/ Person(const Person& p) { cout << "Person的拷貝建構函式呼叫" << endl; m_Age = p.m_Age; } ~Person() { cout << "Person的解構函式呼叫" << endl; } int m_Age; }; //void test01() { // Person p; // p.m_Age = 18; // Person p2(p); // cout << "p2的年齡為:" << p2.m_Age << endl; //} void test02() { Person p(28); Person p2(p); cout << "p2的年齡為:" << p2.m_Age << endl; } int main() { //test01(); test02(); system("pause"); return 0; }
#include<iostream> using namespace std; //深拷貝與淺拷貝 class Person { public: Person() { cout << "Person的預設建構函式呼叫" << endl; } Person(int age,int height) { m_Age = age; m_Height = new int(height); cout << "Person的有參建構函式呼叫" << endl; } Person(const Person &p) { cout << "Person 拷貝建構函式的呼叫" << endl; m_Age = p.m_Age; //m_Height = p.m_Height; 編譯器預設實現就是這行程式碼 //深拷貝操作 //如果不利於深拷貝在堆區建立記憶體,會導致淺拷貝帶來的重複釋放堆區問題 m_Height = new int(*p.m_Height); } ~Person() { //解構堆區,將堆區開闢資料做釋放操作 if (m_Height != NULL) { delete m_Height; m_Height = NULL; //淺拷貝帶來的問題就是堆區的問題重複釋放 //淺拷貝的問題 要利用深拷貝進行解決 } cout << "Person的解構函式呼叫" << endl; } int m_Age;//年齡 int* m_Height;//身高 }; void test01() { Person p1(18,160); cout << "p1的年齡為:" << p1.m_Age <<"身高為:"<<*p1.m_Height << endl; Person p2(p1); cout << "p2的年齡為:" << p2.m_Age <<"身高為:"<<*p2.m_Height << endl; } int main() { test01(); system("pause"); return 0; }
如果屬性有在堆區開闢的,一定要自己提供拷貝建構函式,防止淺拷貝帶來的問題
作用:c++提供了初始化列表語法,用來初始化屬性
語法:建構函式():屬性1(值1),屬性2(值2)...{}
#include<iostream> using namespace std; //初始化列表 class Person { public: //傳統初始化操作 /*Person(int a, int b, int c) { m_A = a; m_B = b; m_C = c; }*/ //初始化列表初始化屬性 Person(int a,int b,int c) :m_A(a), m_B(b), m_C(c) { } int m_A; int m_B; int m_C; }; void test01() { //Person p(10, 20, 30); Person p(30,20,10); cout << "m_A = " << p.m_A << endl; cout << "m_B = " << p.m_B << endl; cout << "m_C = " << p.m_C << endl; } int main() { test01(); system("pause"); return 0; }
c++類中的成員可以是另一個類的物件,我們稱該成員為 物件成員
例如:
class A{}
class B
{
A a;
}
B類中有物件A作為成員去,A為物件成員
#include<iostream> using namespace std; //類物件作為類成員 //手機類 class Phone { public: Phone(string pName) { cout << "Phone的建構函式呼叫" << endl; m_PName = pName; } ~Phone() { cout << "Phone的解構函式呼叫" << endl; } //手機品牌名稱 string m_PName; }; //人類 class Person { public: //Phone m_Phone = pName 隱式轉換法 Person(string name, string pName):m_Name(name),m_Phone(pName) { cout << "Person的建構函式呼叫" << endl; } ~Person() { cout << "Person的解構函式呼叫" << endl; } //姓名 string m_Name; //手機 Phone m_Phone; }; //當其他類物件作為本類成員,構造時先構造類物件,再構造自身,解構的順序與構造相反 void test01() { Person p("張三","蘋果"); cout << p.m_Name << "拿著" << p.m_Phone.m_PName << endl; } int main() { test01(); system("pause"); return 0; }
靜態成員就是在成員變數和成員函數前加上關鍵字static,稱為靜態成員
靜態成員分為:
靜態成員變數
所有物件共用一份資料
在編譯階段分配記憶體
類內宣告,類外初始化
靜態成員函數
所有物件共用同一個函數
靜態成員函數只能存取靜態成員變數
#include<iostream> using namespace std; //靜態成員函數 //所有物件共用同一個函數 //靜態成員函數只能存取靜態成員變數 class Person { public: //靜態成員函數 static void func() { m_A = 100;//靜態成員函數可以存取靜態成員變數 //m_B = 200;//靜態成員函數不可以存取非靜態成員變數,無法區分到底是哪個m_B cout << "static void func的呼叫" << endl; } static int m_A;//靜態成員變數 int m_B;//非靜態成員變數 //靜態成員函數也是有存取許可權的 private: static void func2() { cout << "static void func2的呼叫" << endl; } }; int Person::m_A = 0; //有兩種存取方式 void test01() { //1.通過物件進行存取 Person p; p.func(); //2.通過類名存取 Person::func(); //Person::func2();類外存取不到私有的靜態成員函數 } int main() { test01(); system("pause"); return 0; }
在c++中,類的成員變數和成員函數分開儲存
只有非靜態成員變數才屬於類的物件上
#include<iostream> using namespace std; //成員變數和成員函數是分開儲存的 class Person { int m_A;//非靜態成員變數 屬於類的物件上的 static int m_B;//靜態成員變數 不屬於類的物件上 void func() {}//非靜態成員函數 不屬於類的物件上 static void func2() {}//靜態成員函數 不屬於類的物件上 }; int Person::m_B = 0; void test01() { Person p; //空物件佔用的記憶體空間為:1 //c++編譯器會給每個空物件也分配一個位元組空間,是為了區分空物件佔記憶體的位置 //每個空物件也應該有一個獨一無二的記憶體地址 cout << "size of p = "<<sizeof(p) << endl; } void test02() { Person p; cout << "size of p = " << sizeof(p) << endl; } int main() { //test01(); test02(); system("pause"); return 0; }
this指標的用途:
當形參和成員變數同名時,可用this指標來區分
在類的非靜態成員函數中返回物件本身,可使用return * this返回
#include<iostream> using namespace std; class Person { public: Person(int age) { //this指標指向被呼叫的成員函數所屬的物件 this->age = age; } int age; Person PersonAddAge(Person &p) { this->age += p.age; //this指向p2的指標,而*this指向的就是p2這個物件本體 return *this; } }; //1.解決名稱衝突 void test01() { Person p1(18); cout << "p1的年齡為:" << p1.age << endl; } //2.返回物件本身用*this void test02() { Person p1(10); Person p2(10); //鏈式程式設計思想 p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1); cout << "p2的年齡為:" << p2.age << endl; } int main() { //test01(); test02(); system("pause"); return 0; }
c++中空指標也是可以呼叫成員函數的,但是也要注意有沒有用到this指標
如果用到this指標,需要加以判斷保證程式碼的健壯性
#include<iostream> using namespace std; //空指標呼叫成員函數 class Person { public: void showClassName() { cout << "this is Person class" << endl; } void showPersonAge() { //報錯原因是因為傳入的指標是為NULL if (this == NULL) { return; } cout << "age = " <<this-> m_Age << endl; } int m_Age; }; void test01() { Person* p = NULL; //p->showClassName(); p->showPersonAge(); } int main() { test01(); system("pause"); return 0; }
常函數
成員函數後加const後我們稱這個函數為常函數
函數內不可以修改成員屬性
成員屬性宣告時加關鍵字mutable後,在常函數中依然可以修改
常物件:
宣告物件前加const稱該物件為常物件
常物件只能呼叫常函數
#include<iostream> using namespace std; //空指標呼叫成員函數 class Person { public: void showClassName() { cout << "this is Person class" << endl; } void showPersonAge() { //報錯原因是因為傳入的指標是為NULL if (this == NULL) { return; } cout << "age = " <<this-> m_Age << endl; } int m_Age; }; void test01() { Person* p = NULL; //p->showClassName(); p->showPersonAge(); } int main() { test01(); system("pause"); return 0; }
友元的目的就是讓一個函數或者類存取另一個類中私有成員
友元關鍵字為friend
友元的三種實現:
#include<iostream> using namespace std; #include<string> //建築物類 class Building { //goodGay全域性函數是Building好朋友,可以存取Building中私有成員 friend void goodGay(Building* building); public: Building() { m_SittingRoom = "客廳"; m_BedRoom = "臥室"; } public: string m_SittingRoom;//客廳 private: string m_BedRoom;//臥室 }; //全域性函數 void goodGay(Building *building) { cout << "好基友全域性函數 正在存取:" << building->m_SittingRoom << endl; cout << "好基友全域性函數 正在存取:"<<building->m_BedRoom << endl; } void test01() { Building building; goodGay(&building); } int main() { test01(); system("pause"); return 0; }
#include<iostream> using namespace std; #include<string> //類做友元 class Building; class GoodGay { public: GoodGay(); void visit();//參觀函數 存取Building中的屬性 Building* building; }; class Building { //GoodGay類是本來的好朋友,可以存取本類中私有成員 friend class GoodGay; public: Building(); public: string m_SittiingRoom;//客廳 private: string m_BedRoom;//臥室 }; //類外寫成員函數 Building::Building() { m_SittiingRoom = "客廳"; m_BedRoom = "臥室"; } GoodGay::GoodGay() { //建立建築物物件 building = new Building; } void GoodGay::visit() { cout << "好基友類正在存取:"<<building->m_SittiingRoom << endl; cout << "好基友類正在存取:" << building->m_BedRoom << endl; } void test01() { GoodGay gg; gg.visit(); } int main() { test01(); system("pause"); return 0; }
#include<iostream> using namespace std; #include<string> class Building; class GoodGay { public: GoodGay(); void visit();//讓visit函數可以存取Building中的私有成員 void visit2();//讓visit函數不可以存取Building中的私有成員 Building* building; }; class Building { //告訴編譯器 GoodGay類下的visit成員函數作為本類的好朋友,可以存取私有成員 friend void GoodGay:: visit(); public: Building(); public: string m_SittingRoom;//客廳 private: string m_BedRoom;//臥室 }; //類外實現成員函數 Building::Building() { m_SittingRoom = "客廳"; m_BedRoom = "臥室"; } GoodGay::GoodGay() { building = new Building; } void GoodGay::visit() { cout << "visit函數正在存取"<<building->m_SittingRoom << endl; cout << "visit函數正在存取" << building->m_BedRoom << endl; } void GoodGay::visit2() { cout << "visit2函數正在存取" << building->m_SittingRoom << endl; //cout << "visit2函數正在存取" << building->m_BedRoom << endl; } void test01() { GoodGay gg; gg.visit(); gg.visit2(); } int main() { test01(); system("pause"); return 0; }
本篇文章就到這裡了,希望能夠給你帶來幫助,也希望您能夠多多關注it145.com的更多內容!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45