新聞中心
- 4.2 對象的初始化和清理
- 4.2.1 構(gòu)造函數(shù)和析構(gòu)函數(shù)
- 4.2.2 構(gòu)造函數(shù)的分類及調(diào)用
- 兩種分類方式:
- 三種調(diào)用方式:
- 4.2.3 拷貝構(gòu)造函數(shù)調(diào)用時機(jī)
- 4.2.4 構(gòu)造函數(shù)調(diào)用規(guī)則
- 4.2.5 深拷貝與淺拷貝
- 4.2.6 初始化列表
- 4.2.7 類對象作為類成員
- 4.2.8靜態(tài)成員
- 靜態(tài)成員變量
- 靜態(tài)成員函數(shù)
c++面向?qū)ο蟮娜筇匦詾椋悍庋b、繼承、多態(tài)
c++認(rèn)為萬事萬物皆為對象,對象上有其屬性和行為
對象的初始化和清理也是兩個非常重要的安全問題
一個對象或者變量沒有初始狀態(tài),對其使用后果是未知
同樣的使用完一個對象或變量,沒有及時清理,也會造成一定的安全問題
c++利用了構(gòu)造函數(shù)和析構(gòu)函數(shù)解決上述問題,這兩個函數(shù)將會被編譯器自動調(diào)用,完成對象初始化和清理工作。對象的初始化和清理工作是編譯器強(qiáng)制要我們做的事情,因此如果我們不提供構(gòu)造和西溝,編譯器會提供。編譯器提供的構(gòu)造函數(shù)和析構(gòu)函數(shù)是空實現(xiàn)
- 構(gòu)造函數(shù): 主要作用在于創(chuàng)建對象時為對象的成員屬性賦值,構(gòu)造函數(shù)有編譯器自動調(diào)用,無需手動調(diào)用。
- 析構(gòu)函數(shù): 主要作用在于對象銷毀前系統(tǒng)自動調(diào)用,執(zhí)行一些清理工作。
構(gòu)造函數(shù)語法:類名(){}
(需在public作用域調(diào)用)
- 構(gòu)造函數(shù),沒有返回值也不寫void
- 函數(shù)名稱與類名相同
- 構(gòu)造函數(shù)可以有參數(shù),因此可以發(fā)生重載
- 程序在調(diào)用對象時候會自動調(diào)用構(gòu)造,無需手動調(diào)用,而且只會調(diào)用一次
析構(gòu)函數(shù)語法:~類名(){}
- 析構(gòu)函數(shù),沒有返回值也不寫void
- 函數(shù)名稱與類名相同,在名稱前加上符號~
- 構(gòu)造函數(shù)不可以有參數(shù),因此不可以發(fā)生重載
- 程序在對象銷毀前會自動調(diào)用析構(gòu),無需手動調(diào)用,而且只會調(diào)用一次
#includeusing namespace std;
//對象的初始化和清理
//1、構(gòu)造函數(shù) 進(jìn)行初始化操作
class Person{public:
Person(){cout<<"Person構(gòu)造函數(shù)的調(diào)用"<cout<<"Person析構(gòu)函數(shù)的調(diào)用"<Person p1;//棧上的數(shù)據(jù),自動釋放
}
int main(){test01();
cout<<"~~~~~~分隔符~~~~~~"<
4.2.2 構(gòu)造函數(shù)的分類及調(diào)用
兩種分類方式:- 按參數(shù)分類:有參構(gòu)造和無參構(gòu)造
- 按類型分類:普通構(gòu)造和拷貝構(gòu)造
class Person{public:
//普通構(gòu)造函數(shù)
Person(){//無參構(gòu)造(編譯器默認(rèn)構(gòu)造)
cout<<"Person的無參構(gòu)造函數(shù)調(diào)用"<//有參構(gòu)造
age=a;
cout<<"Person的有參構(gòu)造函數(shù)調(diào)用"<//將傳入的人身上所有的屬性,拷貝到我身上
age=p.age;
cout<<"Person的拷貝構(gòu)造函數(shù)調(diào)用"<
三種調(diào)用方式:- 括號法(注:調(diào)用無參構(gòu)造函數(shù)時不要加())
Person p1;//無參構(gòu)造
Person p2(10);//有參構(gòu)造
Person p3(p1);//拷貝構(gòu)造
Person p4(p2);//拷貝構(gòu)造
cout<<"p2的年齡:"<
- 顯示法
Person p1;
Person p2=Person(10);//有參構(gòu)造
Person p3=Person(p2);//拷貝構(gòu)造
Person(10);//稱為匿名對象 特點(diǎn):當(dāng)前行執(zhí)行結(jié)束后,系統(tǒng)會立即回收掉匿名對象
Person(p3);//注意:不要利用拷貝構(gòu)造函數(shù)初始化匿名對象
//編譯器認(rèn)為Person(p3)==Person p3; 重定義
- 隱式轉(zhuǎn)換法
Person p1=10;//相當(dāng)于Person p1=Person(10);
Person p2=p1;//拷貝構(gòu)造
4.2.3 拷貝構(gòu)造函數(shù)調(diào)用時機(jī)c++中拷貝構(gòu)造函數(shù)調(diào)用時機(jī)通常有三種情況
- 使用一個已經(jīng)創(chuàng)建完畢的對象來初始化一個新對象
void test1(){Person p1(20);
Person p2(p1);
cout<<"p2的年齡:"<
- 值傳遞的方式給函數(shù)參數(shù)傳值
void test2_1(Person p){}
void test2(){Person p;
test2_1(p);
}
- 以值方式返回局部對象
Person test3_1(){Person p1;
cout<<(int*)&p1<Person p=test3_1();
cout<<(int*)&p<
4.2.4 構(gòu)造函數(shù)調(diào)用規(guī)則默認(rèn)情況下,c++編譯器至少給一個類添加3個函數(shù)
- 默認(rèn)構(gòu)造函數(shù)(無參,函數(shù)體為空)
- 默認(rèn)析構(gòu)函數(shù)(無參,函數(shù)體為空)
- 默認(rèn)拷貝函數(shù),對屬性進(jìn)行值拷貝
構(gòu)造函數(shù)調(diào)用規(guī)則:
- 如果用戶定義有參構(gòu)造函數(shù),c++不再提供默認(rèn)無參構(gòu)造,但會提供默認(rèn)拷貝構(gòu)造
- 如果用戶定義拷貝構(gòu)造函數(shù),c++不再提其他構(gòu)造函數(shù)
int main(){Person p;
p.a=18;
Person p2(p);
cout<<"p2的年齡:"<
//三個函數(shù)均自定義
//若注釋掉無參構(gòu)造,保留有參構(gòu)造,則運(yùn)行Person p,顯示沒有合適的構(gòu)造函數(shù)可用
//若只保留自定義拷貝構(gòu)造,則有參無參構(gòu)造函數(shù)均無
class Person{public:
int a;
Person(){cout<<"無參構(gòu)造函數(shù)調(diào)用"<a=age;
cout<<"有參構(gòu)造函數(shù)調(diào)用"<cout<<"拷貝構(gòu)造函數(shù)調(diào)用"<cout<<"析構(gòu)函數(shù)調(diào)用"<
4.2.5 深拷貝與淺拷貝淺拷貝:簡單的賦值拷貝操作(淺拷貝帶來的問題是堆區(qū)重復(fù)釋放)
深拷貝:在堆區(qū)重新申請空間,進(jìn)行拷貝操作
淺拷貝時完全值復(fù)制,存在兩個相同地址,會通過析構(gòu)函數(shù)釋放兩次,第二次為非法操作
#includeusing namespace std;
class Person{public:
Person(int age,int height){m_Age=age;
m_Height=new int(height);
cout<<"有參構(gòu)造函數(shù)調(diào)用"<cout<<"拷貝構(gòu)造函數(shù)的調(diào)用"<if(m_Height!=NULL){ delete m_Height;
m_Height=NULL;
}
cout<<"析構(gòu)函數(shù)調(diào)用"<Person p1(18,160);
cout<<"p1的年齡為"<
4.2.6 初始化列表作用: c++提供了初始化列表語法,用來初始化屬性
語法:構(gòu)造函數(shù)():屬性1(值1),屬性2(值2)...{}
#includeusing namespace std;
class Person{public:
int m_A;
int m_B;
int m_C;
//傳統(tǒng)初始化操作
// m_A=a;
// m_B=b;
// m_C=c;
// }Person(int a,int b,int c){//初始化列表初始化屬性
Person(int a,int b,int c):m_A(a),m_B(b),m_C(c){}
};
int main(){Person p(10,20,30);
cout<<"m_A="<
4.2.7 類對象作為類成員c++類中的成員可以是另一個類的對象,我們稱該成員為對象成員
例如:
class A{};
class B{A a;
};
B類中有對象A作為成員,A為對象成員
那么,當(dāng)創(chuàng)建B對象時,A與B的構(gòu)造和析構(gòu)的順序是誰先誰后
結(jié)論:當(dāng)其他類對象作為本類成員,構(gòu)造時先構(gòu)造類對象,再構(gòu)造自身;析構(gòu)順序與構(gòu)造相反
#includeusing namespace std;
class Phone{public:
Phone(string name){ m_PhoneName=name;
cout<<"Phone的構(gòu)造"< cout<<"Phone的析構(gòu)"<public:
Person(string name,string pName):m_Name(name),m_Phone(pName){ cout<<"Person的構(gòu)造"< cout<<"Person的析構(gòu)"<Person p("張三","蘋果max");
cout<
4.2.8靜態(tài)成員靜態(tài)成員就是在成員變量和成員函數(shù)前加上關(guān)鍵詞static,成為靜態(tài)成員
靜態(tài)成員分為:
- 所有對象共享同一份數(shù)據(jù)
- 在編譯階段分配內(nèi)存
- 類內(nèi)聲明,類外初始化
1、類內(nèi)聲明,類外初始化
2、靜態(tài)成員變量有訪問權(quán)限
class Person{public:
static int m_A;
private:
static int m_B;//私有 類外不可訪問
};
int Person::m_A=100;
3、靜態(tài)成員變量 不屬于某個對象上,所有對象都共享一份數(shù)據(jù)
void test1(){Person p;
cout<
4、靜態(tài)成員變量的兩種訪問方式
1、通過對象進(jìn)行訪問
2、通過類名進(jìn)行訪問
void test2(){Person p;
//通過對象進(jìn)行訪問
cout<
靜態(tài)成員函數(shù)- 所有對象共享同一個函數(shù)
- 靜態(tài)成員函數(shù)只能訪問靜態(tài)成員變量
1、靜態(tài)成員函數(shù)有訪問權(quán)限
2、靜態(tài)成員函數(shù)只能訪問靜態(tài)成員變量
class Person{public:
static void func(){m_A=100; //靜態(tài)成員函數(shù)可以訪問靜態(tài)成員變量
// m_B=200; //靜態(tài)成員函數(shù)不可以訪問非靜態(tài)成員變量
cout<<"static void func調(diào)用"<//類外不可訪問私有靜態(tài)成員函數(shù)
cout<<"static void func2調(diào)用"<
3、兩種訪問方式
void test1(){//通過對象訪問
Person p;
p.func();
//通過類名訪問
Person::func();
}
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
名稱欄目:c++基礎(chǔ)-類與對象2-創(chuàng)新互聯(lián)
標(biāo)題網(wǎng)址:http://www.dlmjj.cn/article/pgjhp.html