最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

C++繼承、派生、訪問(wèn)權(quán)限、成員對(duì)象、插入運(yùn)算符重載

2023-09-13 10:17 作者:虛云幻仙  | 我要投稿

#include <iostream>

using namespace std;


//繼承inherit 派生derive。子類(lèi)繼承父類(lèi)?;?lèi)派生出派生類(lèi)。兩個(gè)詞描述的是一件事情

class ClassBase1 //聲明基類(lèi)

{

????public:

???? int pub; //公有

????protected:

???? int pro; //保護(hù),類(lèi)及子類(lèi)外不可調(diào)用

????private:

???? int pri; //私有,類(lèi)外不可調(diào)用

};

class ClassDerive1 :public ClassBase1 //派生類(lèi)。繼承基類(lèi)。繼承的格式為: class 類(lèi)名:[public/protected/private] 基類(lèi)名 ,訪問(wèn)修飾符不寫(xiě)默認(rèn)private

{

???? void accessbasemember()

???? {

???????? pub = 3; //在public繼承基類(lèi)時(shí),基類(lèi)的public成員在子類(lèi)中仍然是public可直接訪問(wèn)

???????? pro = 2; //在public繼承基類(lèi)時(shí),基類(lèi)的protected成員在子類(lèi)中仍然是protected可直接訪問(wèn),但類(lèi)及子類(lèi)外不可訪問(wèn)。比如在main中創(chuàng)建對(duì)象,通過(guò)對(duì)象不能調(diào)用protected成員

???????? //報(bào)錯(cuò):pri = 1; //在public繼承基類(lèi)時(shí),基類(lèi)的private成員在子類(lèi)中不可訪問(wèn),要想訪問(wèn)需要通過(guò)父類(lèi)的接口。所以private成員和protected成員的區(qū)別是子類(lèi)中是否能訪問(wèn),在類(lèi)外通過(guò)創(chuàng)建對(duì)象的話兩者都不能訪問(wèn)。同樣子類(lèi)的子類(lèi)不可以訪問(wèn)父類(lèi)們(無(wú)論哪一級(jí))的private成員。即ClassDerive1的子類(lèi)也不可訪問(wèn)ClassBase1的private成員

???? }

};

class ProtectedDerive1 :protected ClassBase1 //protected繼承,會(huì)將父類(lèi)的所有public成員作為protected訪問(wèn)權(quán)限

{

???? void accessbasemember()

???? {

???????? pub = 20; //這里pub變成了protected。即外部不能通過(guò)創(chuàng)建這個(gè)類(lèi)的對(duì)象來(lái)訪問(wèn)了(不影響父類(lèi)的對(duì)象訪問(wèn)public成員)。且這個(gè)類(lèi)的public/protected子類(lèi)也將pub作為protected訪問(wèn)來(lái)繼承

???????? pro = 10; //依然是protected保持不變

???????? //pri = 0; 依然不能訪問(wèn),且子子類(lèi)也不能,所以如果需要在子類(lèi)中直接使用這個(gè)成員,并且不希望外部訪問(wèn)這個(gè)成員,就應(yīng)該聲明為protected

???? }

};

class PrivateDerive1 :private ClassBase1 //private繼承,可省略,不寫(xiě)修飾詞默認(rèn)是private

{

void accessbasemember()

{

???? pub = 30; //pub作為private繼承。這意味著外部不能調(diào)用。且子子類(lèi)不能訪問(wèn)

???? pro = 20; //pro作為private繼承。這使得這個(gè)成員在子子類(lèi)中不能訪問(wèn)了。任何這個(gè)類(lèi)的子類(lèi)(無(wú)論三種訪問(wèn)修飾)都不能訪問(wèn)這個(gè)類(lèi)的任何成員了

???? //pri = 0; 依然不能訪問(wèn)

}

//雖然父類(lèi)們的private成員不能訪問(wèn),但可以通過(guò)父類(lèi)們的接口訪問(wèn),這說(shuō)明父類(lèi)們所有的數(shù)據(jù)成員都會(huì)被繼承,只是有些不能訪問(wèn)

//三種繼承方式不影響子類(lèi)中的新成員訪問(wèn)權(quán)限

public:

int d1; //依然公有

protected:

int d2;

private:

int d3;

public:

using ClassBase1::pub; //在私有繼承中可以通過(guò)using 基類(lèi)::成員 將基類(lèi)的數(shù)據(jù)成員或成員函數(shù)重新定義訪問(wèn)權(quán)限,原本因?yàn)樗接欣^承而私有的pub在public下using使得對(duì)外部可見(jiàn)

};

//通常使用public繼承


class ClassBase2 //父類(lèi)

{

????public:

???? int base;

???? ClassBase2() { cout << "base no parameter" << endl; } //無(wú)參構(gòu)造器

???? ClassBase2(int base)

???? :base(base) //通過(guò)列表初始化時(shí)不能使用this,也就是說(shuō)這里的初始化發(fā)生在產(chǎn)生對(duì)象之前

???? { cout << "base 1 parameter" << endl; } //有參構(gòu)造器

???? ~ClassBase2() { cout << "base destructor" << endl; } //析構(gòu)器

???? ClassBase2(const ClassBase2& another):base(another.base){ cout << "base copy" << endl; } //拷貝構(gòu)造器

???? ClassBase2& operator=(const ClassBase2& another) //賦值運(yùn)算符重載

???? //: base(another.base)? 報(bào)錯(cuò)。說(shuō)明列表初始化只能在構(gòu)造階段使用。對(duì)已有的對(duì)象重新賦值不能調(diào)用

???? {

???????? if(&another!=this)

???????? ???? base = another.base;

???????? cout << "base operator=" << endl;

???????? return *this;

???? }

};

class ClassDerive2:public ClassBase2{}; //子類(lèi)。子類(lèi)會(huì)繼承父類(lèi) 除構(gòu)造器、析構(gòu)器、拷貝構(gòu)造器、賦值重載 之外的所有內(nèi)容。 這里子類(lèi)沒(méi)有手動(dòng)定義構(gòu)造器等,程序默認(rèn)生成public的四類(lèi)函數(shù)

int maininherit1()

{

???? ClassBase2 b1; //調(diào)用"base no parameter" "base destructor"

???? ClassDerive2 d1; //調(diào)用"base no parameter" "base destructor",即子類(lèi)自動(dòng)生成的構(gòu)造器會(huì)自動(dòng)調(diào)用父類(lèi)的 無(wú)參 構(gòu)造器,且先構(gòu)造父類(lèi)再構(gòu)造子類(lèi)。子類(lèi)自動(dòng)生成的析構(gòu)器會(huì)自動(dòng)調(diào)用父類(lèi)的析構(gòu)器,且先析構(gòu)子類(lèi)再析構(gòu)父類(lèi)(后進(jìn)先出),無(wú)論子類(lèi)是否顯式聲明了析構(gòu)器,子類(lèi)的析構(gòu)器在用戶(hù)定義的代碼之后會(huì)自動(dòng)調(diào)用父類(lèi)的析構(gòu)器

???? ClassBase2 b2(2); //帶參構(gòu)造器 調(diào)用"base 1 parameter" "base destructor"

???? //報(bào)錯(cuò):ClassDerive2 b2(2); 子類(lèi)不繼承父類(lèi)的任何構(gòu)造器

???? ClassBase2 b3(b2); //調(diào)用"base copy" 析構(gòu)器不再贅述

???? ClassDerive2 d2(d1); //調(diào)用"base copy" ,子類(lèi)默認(rèn)生成的拷貝構(gòu)造器會(huì)自動(dòng)調(diào)用父類(lèi)的拷貝構(gòu)造器

???? d2 = d1; //調(diào)用"base operator=" ,子類(lèi)默認(rèn)生成的賦值運(yùn)算符重載函數(shù)會(huì)自動(dòng)調(diào)用父類(lèi)的

???? //所以子類(lèi)雖然不繼承父類(lèi)的這四類(lèi)函數(shù),卻會(huì)在默認(rèn)情況下使用,這里不繼承是指不會(huì)將父類(lèi)的四類(lèi)函數(shù)作為當(dāng)前函數(shù)的四類(lèi)函數(shù)以直接使用

????

???? //對(duì)象的創(chuàng)建必須進(jìn)行初始化。所以ClassDerive2對(duì)象創(chuàng)建時(shí)調(diào)用了ClassDerive2的構(gòu)造器

???? //但ClassDerive2對(duì)象在屬于ClassDerive2類(lèi)之前先屬于ClassBase2類(lèi)。在分配好內(nèi)存之后,程序先對(duì)ClassDerive2內(nèi)存塊中的ClassBase2部分初始化,再對(duì)ClassDerive2部分進(jìn)行初始化。所以雖然看起來(lái)是創(chuàng)建了兩個(gè)對(duì)象,實(shí)際是子類(lèi)對(duì)象中保留的父類(lèi)對(duì)象區(qū)域,而既然這個(gè)區(qū)域是父類(lèi)對(duì)象,就要進(jìn)行對(duì)象的初始化,所以會(huì)執(zhí)行父類(lèi)的構(gòu)造器

???? return 0;

}

class ClassDerive3 :public ClassBase2 //另一個(gè)子類(lèi)

{

????public:

???? ClassDerive3() {} //手動(dòng)聲明默認(rèn)構(gòu)造器,程序不再自動(dòng)生成。這里沒(méi)有顯式調(diào)用父類(lèi)構(gòu)造器,默認(rèn)會(huì)調(diào)用父類(lèi)的無(wú)參構(gòu)造器來(lái)初始化父類(lèi)的區(qū)域。如果父類(lèi)沒(méi)有無(wú)參構(gòu)造器就會(huì)報(bào)錯(cuò)

???? ClassDerive3(int v) //手動(dòng)聲明有參構(gòu)造器,只要是構(gòu)造器(無(wú)論默認(rèn)還是拷貝),只要沒(méi)有顯式調(diào)用父類(lèi)構(gòu)造器,就會(huì)默認(rèn)調(diào)用父類(lèi)無(wú)參構(gòu)造器

???? :ClassBase2(v) //顯式調(diào)用父類(lèi)構(gòu)造器,調(diào)用的位置只能寫(xiě)在這里,不能寫(xiě)在{}中,如果不寫(xiě)的話默認(rèn)在這里寫(xiě)作:ClassBase2()無(wú)參構(gòu)造器。

???? //:ClassBase2() //無(wú)參可省略,也就意味著調(diào)用子類(lèi)的這個(gè)構(gòu)造器,在執(zhí)行到{}之前,都會(huì)調(diào)用冒號(hào)這里指定的父類(lèi)構(gòu)造器來(lái)初始化

???? {

???? //錯(cuò)誤:ClassBase2(v);如果在這里寫(xiě),就是額外生成一個(gè)當(dāng)前塊作用域內(nèi)的對(duì)象,而非對(duì)當(dāng)前對(duì)象的父類(lèi)區(qū)域進(jìn)行父類(lèi)初始化

???? }

???? ClassDerive3(const ClassDerive3& another)

???? //這里不寫(xiě)父類(lèi)構(gòu)造器的話,默認(rèn)使用父類(lèi)無(wú)參構(gòu)造器而不是拷貝構(gòu)造器。因?yàn)榭截悩?gòu)造器也只是構(gòu)造器的一種重載。不手動(dòng)定義拷貝構(gòu)造器會(huì)把調(diào)用父類(lèi)拷貝構(gòu)造器的模板直接粘過(guò)來(lái)。手動(dòng)定義了程序就將這個(gè)構(gòu)造器一視同仁,都添加無(wú)參構(gòu)造器

???? //:ClassBase2(another) 手動(dòng)指定,這時(shí)父類(lèi)構(gòu)造器接收到子類(lèi)的參數(shù),先嚴(yán)格匹配,沒(méi)有找到ClassBase2(ClassDerive3)重載構(gòu)造器時(shí),再將參數(shù)隱式轉(zhuǎn)換為ClassBase2類(lèi)型

???? //:ClassBase2(another.base) 也可以調(diào)用父類(lèi)的有參構(gòu)造器,想用哪個(gè)都可以

???? {}

????

???? ClassDerive3& operator=(const ClassDerive3& another)

???? //注意這里不能用 :xxxxx? 因?yàn)檫@個(gè)函數(shù)不是構(gòu)造器,而是函數(shù)成員

???? {

???????? if (&another == this)

???????????? return *this;

???????? //默認(rèn)生成的operator= 會(huì)在這里調(diào)用父類(lèi)的賦值函數(shù),手動(dòng)定義則需要手動(dòng)寫(xiě),不寫(xiě)不調(diào)用。因?yàn)檫@不同于構(gòu)造器,創(chuàng)建對(duì)象時(shí)必須初始化,所以必須調(diào)用構(gòu)造器,但賦值不是創(chuàng)建對(duì)象,不必須調(diào)用父類(lèi)的賦值函數(shù)

???????? //錯(cuò)誤:operator=(another); 這樣寫(xiě)會(huì)調(diào)用當(dāng)前函數(shù),變成無(wú)限遞歸

???????? ClassBase2::operator=(another); //正確寫(xiě)法。在子類(lèi)中通過(guò)父類(lèi)的名稱(chēng)空間訪問(wèn)父類(lèi)的函數(shù)成員

???????? //ClassDerive3::operator=(another); //有效 當(dāng)前類(lèi)可以通過(guò)當(dāng)前類(lèi)的名稱(chēng)空間訪問(wèn)當(dāng)前類(lèi)的函數(shù)成員

???????? //this->ClassDerive3::operator=(another); //有效

???????? //base; //有效

???????? //ClassBase2::base; //有效

???????? //this->base; //有效

???????? //this->ClassDerive3::base; //有效

???????? //ClassDerive3::base; //有效

???????? //結(jié)論:在類(lèi)外不能通過(guò)類(lèi)的名稱(chēng)空間訪問(wèn)類(lèi)的函數(shù)成員,因?yàn)楹瘮?shù)成員屬于對(duì)象,沒(méi)有對(duì)象不能調(diào)用。但在類(lèi)內(nèi)可以通過(guò)名稱(chēng)空間訪問(wèn)函數(shù)成員。這個(gè)過(guò)程會(huì)默認(rèn)使用當(dāng)前對(duì)象 *this

???????? //當(dāng)前類(lèi)的operator=會(huì)遮擋父類(lèi)的operator=函數(shù),無(wú)論參數(shù)列表是否相同,只要重名就是擋住,不能直接訪問(wèn)。這稱(chēng)為shadow。解決方法為使用父類(lèi)名稱(chēng)空間注明函數(shù)歸屬

???????? return *this;

???? }

};


class ClassDerive4 :public ClassBase2

{

????public:

???? const int conval; //const類(lèi)型。c++中要求必須執(zhí)行初始化,這和對(duì)象相似。

???? ClassBase1 b1; //在類(lèi)中聲明一個(gè)對(duì)象數(shù)據(jù)成員。即在ClassDerive4對(duì)象中保存一個(gè)完整的ClassBase1對(duì)象區(qū)域。因?yàn)槁暶鲗?duì)象必須初始化,所以這也和const成員類(lèi)似

???? ClassDerive4()

???? : conval(0),b1(ClassBase1()), ClassBase2(2) //需要初始化的const成員、父類(lèi)、對(duì)象數(shù)據(jù)成員都需要寫(xiě)在 :這里進(jìn)行初始化。即便將父類(lèi)構(gòu)造器寫(xiě)在最后,也會(huì)最先調(diào)用,再對(duì)其他值進(jìn)行初始化。而成員初始化的順序是按照聲明的順序,所以即便先寫(xiě)b1()再寫(xiě)conval()也是先初始化conval

???? //成員的初始化相當(dāng)于 const int conval = 0;? ClassBase1 b1 = ClassBase1(); 所以b1是直接初始化而不是先構(gòu)造再拷貝構(gòu)造。

???? {

???? //必須初始化的內(nèi)容不能寫(xiě)在這里??梢圆怀跏蓟某蓡T可以寫(xiě)在這里,比如ClassBase1* ptr ,類(lèi)的指針和類(lèi)的對(duì)象不同,因?yàn)轭?lèi)的指針并沒(méi)有創(chuàng)建對(duì)象,所以不必須初始化

???? }

???? //創(chuàng)建ClassDerive4對(duì)象的過(guò)程:分配內(nèi)存->調(diào)用ClassBase2構(gòu)造器初始化父類(lèi)區(qū)域->調(diào)用ClassBase1構(gòu)造器初始化對(duì)象成員->執(zhí)行ClassDerive4構(gòu)造器的函數(shù)體

???? //釋放對(duì)象的過(guò)程永遠(yuǎn)和創(chuàng)建的過(guò)程相反(后進(jìn)先出):執(zhí)行~ClassDerive4析構(gòu)器->調(diào)用~ClassBase1析構(gòu)器->調(diào)用~ClassBase2析構(gòu)器->釋放內(nèi)存 ,析構(gòu)ClassDerive4對(duì)象并不會(huì)清空ClassBase1對(duì)象成員的內(nèi)容,因?yàn)槲鰳?gòu)器的目的是釋放堆內(nèi)存。所以三個(gè)區(qū)域各自析構(gòu)。最后安全釋放內(nèi)存,不需要在ClassDerive4的析構(gòu)器中手動(dòng)調(diào)用ClassBase1的析構(gòu)器,即不用在類(lèi)析構(gòu)器中調(diào)用成員對(duì)象的析構(gòu)器。

};


ostream& operator<<(ostream& out, const ClassBase2& c) //重載全局函數(shù),插入運(yùn)算符,實(shí)現(xiàn)cout<<ClassBase2對(duì)象

{

???? out << c.base;

???? return out; //接收和返回ostream&均為非const,因?yàn)榱鲗?duì)象在使用中可能更改流狀態(tài)

}

ostream& operator<<(ostream& out, const ClassDerive4& c)

{

???? //錯(cuò)誤:out << c; 相當(dāng)于operator<<(out,c)。根據(jù)嚴(yán)格匹配,會(huì)調(diào)用函數(shù)自身,無(wú)限遞歸

???? out << static_cast<const ClassBase2&>(c); //正確用法。需要將 const ClassDerive4& 轉(zhuǎn)換成 const ClassBase2& 來(lái)調(diào)用打印父類(lèi)的函數(shù)。類(lèi)型轉(zhuǎn)換應(yīng)該寫(xiě)完整。有的情況下將const ClassDerive4& c轉(zhuǎn)換成ClassBase2不會(huì)產(chǎn)生問(wèn)題(雖然程序內(nèi)部的執(zhí)行依然有區(qū)別),但只是僥幸運(yùn)行正常。類(lèi)型轉(zhuǎn)換應(yīng)寫(xiě)完整類(lèi)型

???? out << endl << c.conval;

???? return out;

}


class BaseUDM

{

???? char* data;

????public:

???? BaseUDM()

???? {

???????? data = new char[20];

???????? cout << "base constructor" << endl;

???? }

???? BaseUDM(const BaseUDM& another)

???? {

???????? data = new char[20];

???????? cout << "base copy constructor" << endl;

???? }

???? ~BaseUDM()

???? {

???????? delete[]data;

???????? cout << "base destructor" << endl;

???? }

???? BaseUDM& operator=(const BaseUDM& another)

???? {

???????? if (this == &another)return *this;

???????? cout << "base operator" << endl;

???????? //省略賦值過(guò)程

???? }

};

class MemberUDM

{

???? char* data;

????public:

???? MemberUDM()

???? {

???????? data = new char[20];

???????? cout << "member constructor" << endl;

???? }

???? MemberUDM(const MemberUDM& another)

???? {

???????? data = new char[20];

???????? cout << "member copy constructor" << endl;

???? }

???? ~MemberUDM()

???? {

???????? delete[]data;

???????? cout << "member destructor" << endl;

???? }

???? MemberUDM& operator=(const MemberUDM& another)

???? {

???????? if (this == &another)return *this;

?????? ? cout << "member operator" << endl;

???????? //省略賦值過(guò)程

???? }

};

class DeriveUDM:public BaseUDM

{

???? MemberUDM mem;

???? //在派生類(lèi)不使用動(dòng)態(tài)內(nèi)存的情況下,對(duì)于使用動(dòng)態(tài)內(nèi)存的基類(lèi)和使用動(dòng)態(tài)內(nèi)存的成員對(duì)象,默認(rèn)的構(gòu)造器、析構(gòu)器、拷貝構(gòu)造器、賦值運(yùn)算符均可以正確工作,即在派生類(lèi)函數(shù)中自動(dòng)調(diào)用成員、基類(lèi)的對(duì)應(yīng)的函數(shù)

};


class DeriveUDM2 :public BaseUDM

{

???? MemberUDM mem;

???? char* deriveData_;

???? //當(dāng)派生類(lèi)需要使用動(dòng)態(tài)內(nèi)存時(shí),不得不手動(dòng)定義這幾類(lèi)函數(shù)來(lái)完成深拷貝

????public:

???? DeriveUDM2() //如果要使用基類(lèi)默認(rèn)構(gòu)造器、成員默認(rèn)構(gòu)造器以外的構(gòu)造器需要顯式指定

???? {

???? ????deriveData_ = new char[20];

???? }

???? DeriveUDM2(const DeriveUDM2& another)

???? :BaseUDM(another), mem(another.mem) //默認(rèn)的派生類(lèi)拷貝構(gòu)造器會(huì)使用基類(lèi)的拷貝構(gòu)造器及成員的拷貝構(gòu)造器,手動(dòng)定義時(shí)則需要指定否則會(huì)調(diào)用默認(rèn)構(gòu)造器

???? {

???? ????deriveData_ = new char[20];

???? }

???? ~DeriveUDM2()

???? {

???? ????delete[]deriveData_; //析構(gòu)器依然會(huì)自動(dòng)調(diào)用基類(lèi)、成員的析構(gòu)器,所以只需要處理派生類(lèi)的動(dòng)態(tài)內(nèi)存

???? }

???? DeriveUDM2& operator=(const DeriveUDM2& another)

???? {

???????? if (this == &another)return *this;

???????? BaseUDM::operator=(another);//對(duì)于派生類(lèi)中的基類(lèi)部分(子對(duì)象)需要顯式調(diào)用BaseUDM::operator=避免遞歸

???????? mem = another.mem; //等價(jià)于mem.operator=(another.mem)

???????? //省略賦值過(guò)程

???? }

???? //除析構(gòu)器自動(dòng)完成以外,其他函數(shù)都要考慮使用基類(lèi)、成員的哪個(gè)函數(shù)

};


C++繼承、派生、訪問(wèn)權(quán)限、成員對(duì)象、插入運(yùn)算符重載的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
新河县| 玛沁县| 乐安县| 喀喇沁旗| 罗田县| 灵寿县| 天柱县| 视频| 化德县| 射洪县| 西昌市| 楚雄市| 西充县| 白城市| 石台县| 阿克| 安泽县| 富裕县| 当阳市| 贵南县| 竹北市| 栖霞市| 洛川县| 彰化县| 唐河县| 于都县| 菏泽市| 博客| 北安市| 留坝县| 江永县| 广昌县| 石景山区| 合山市| 太白县| 调兵山市| 广西| 伊通| 莎车县| 通道| 余庆县|