![C++課件第7 章類與對(duì)象_第1頁](http://file4.renrendoc.com/view/1bf9caed2c559c4a32b32416d0955a55/1bf9caed2c559c4a32b32416d0955a551.gif)
![C++課件第7 章類與對(duì)象_第2頁](http://file4.renrendoc.com/view/1bf9caed2c559c4a32b32416d0955a55/1bf9caed2c559c4a32b32416d0955a552.gif)
![C++課件第7 章類與對(duì)象_第3頁](http://file4.renrendoc.com/view/1bf9caed2c559c4a32b32416d0955a55/1bf9caed2c559c4a32b32416d0955a553.gif)
![C++課件第7 章類與對(duì)象_第4頁](http://file4.renrendoc.com/view/1bf9caed2c559c4a32b32416d0955a55/1bf9caed2c559c4a32b32416d0955a554.gif)
![C++課件第7 章類與對(duì)象_第5頁](http://file4.renrendoc.com/view/1bf9caed2c559c4a32b32416d0955a55/1bf9caed2c559c4a32b32416d0955a555.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第7章類與對(duì)象
7.1類與對(duì)象的定義與使用
一、類和對(duì)象的定義
類可以理解為用戶定義的數(shù)據(jù)類型,而“int”和“double”是系統(tǒng)定義的簡單數(shù)據(jù)類型。
變量是簡單數(shù)據(jù)類型的實(shí)例,對(duì)象是類的實(shí)例。
一個(gè)對(duì)象由幾個(gè)簡單數(shù)據(jù)類型的變量,和幾個(gè)函數(shù),封裝在一起組成。把數(shù)據(jù)和函數(shù)封裝在
一起組成對(duì)象,是面向?qū)ο蠹夹g(shù)的基本特征。
用成員訪問符訪問對(duì)象中的成員。也可以用指向?qū)ο蟮闹羔樤L問,此時(shí)”(*p).a”等效于
例:復(fù)數(shù)類
classcomplex
(
private:〃復(fù)數(shù)的實(shí)部和虛部
doublereal;
doubleimage;
public:
voidset(doubler,doublei)〃共有函數(shù)成員,設(shè)定復(fù)數(shù)值
(
real=r;
image=i;
)
voiddislayO〃輸出復(fù)數(shù)值
(
cout?real?',+M?image?,,i',?endl;
)
};
voidmain()
(
complexx,y,*p;
x.set(l,3);〃調(diào)用對(duì)象x的成員函數(shù),設(shè)定復(fù)數(shù)值
y.set(3,5);
x.dislayO;
y.dislayO;
p=&x;
(*p).set(6,6);
p->dislay();
cout?x.real;〃錯(cuò)誤,私有成員只能被complex類的成員函數(shù)訪問,不能被main函數(shù)
訪問
注意:
1.定義類時(shí),用關(guān)鍵字“public""private”"protected”來表示各數(shù)據(jù)成員和函數(shù)成員的訪問權(quán)
限。公有權(quán)限的成員,在程序的任何位置都可以被訪問:私有和保護(hù)權(quán)限的成員,只有本類
(不是本對(duì)象)的成員函數(shù)可以訪問。
2.用關(guān)鍵字“class”和“struct”都可以定義類,區(qū)別在于,不指定訪問權(quán)限的情況下,“struct”
默認(rèn)公有,包括公有成員和公有繼承;“class”默認(rèn)私有,包括私有成員和私有繼承。
3.類的定義只是說明了?組對(duì)象的共同特征,所以類定義中說明的數(shù)據(jù)成員并不是具體的
變量,沒有分配內(nèi)存空間,也不能賦初值。定義對(duì)象的時(shí)候,才會(huì)把類實(shí)例化,對(duì)象的數(shù)據(jù)
成員有對(duì)應(yīng)的內(nèi)存空間。
4.類定義結(jié)尾有分號(hào)
二、定義對(duì)象的其他方法
I.定義類的同時(shí)定義對(duì)象
classcomplex
(
private:〃復(fù)數(shù)的實(shí)部和虛部
doublereal;
doubleimage;
public:
voidset(doubler,doublei)〃共有函數(shù)成員,設(shè)定復(fù)數(shù)值
(
real=r;
image=i;
)
voiddislay()〃輸出復(fù)數(shù)值
(
cout?real?"+"?image?"i"?endl;
)
}x,y;
定義類以后立刻定義了對(duì)象,因?yàn)轭惗x是放在全局位置,這里的“x”和“尸兩個(gè)對(duì)象也是全
局變量。
2.不出現(xiàn)類名定義對(duì)象
class
(
private:〃復(fù)數(shù)的實(shí)部和虛部
doublereal;
doubleimage;
public:
voidset(doubler,doublei)〃共有函數(shù)成員,設(shè)定復(fù)數(shù)值
real=r;
image=i;
voiddislayO〃輸出復(fù)數(shù)值
cout?real?',+"?image?,'i,'?endl;
}x,y;
因?yàn)轭悰]有名字,以后不能再定義該類的對(duì)象,這個(gè)類只有“x”和“y”兩個(gè)對(duì)象。
三、定義類時(shí),可以把成員函數(shù)的實(shí)現(xiàn)代碼放到類外
classcomplex
(
private:
doublereal;
doubleimage;
public:
voidset(doubler,doublei);
voiddislayO;
);
voidcomplex::set(doubleredoublei)
(
real=r;
image=i;
)
voidcomplex::dislay()
(
cout?real?"+"?image?"i"?endl;
)
注:
L"::“是作用域操作符,函數(shù)名前加“complex::"表示“set”和“dislay”函數(shù)是類“complex”的成員
函數(shù)。
2.當(dāng)類的成員函數(shù)實(shí)現(xiàn)代碼寫在類內(nèi)部時(shí),這個(gè)函數(shù)被默認(rèn)定義成內(nèi)聯(lián)函數(shù)。實(shí)現(xiàn)代碼寫
在類外部的函數(shù),要想定義成內(nèi)聯(lián)函數(shù),需加關(guān)鍵字“inline”。
7.2類的特殊成員
一、this指針
在對(duì)象調(diào)用自己的非靜態(tài)成員函數(shù)時(shí),會(huì)自動(dòng)傳給成員函數(shù)一個(gè)指針參數(shù)“this”,這個(gè)指針
指向該對(duì)象自己。該參數(shù)是隱含的不可見,在被調(diào)用的成員函數(shù)內(nèi),出現(xiàn)的所有本類成員前
都隱含的加上“this->”,也可以顯式使用this指針。
例:
classcomplex
private:
doublereal;
doubleimage;
public:
voidset(doubler,doublei)
(
this->real=r;
this->image=i;
)
voiddisplay()
(
cout?real?',+',?image?',i"?endl;
}
);
voidmain()
(
complexx,y;
x.set(l,3);
x.displayO;
y.set(3,5);
y.display();
)
注:“set”函數(shù)把this指針顯式寫出了,和原先效果-樣。this指針使得對(duì)象能夠訪問自己的
成員。
二、靜態(tài)成員
類的靜態(tài)成員屬于類本身,而不屬于具體的某個(gè)對(duì)象,所以一個(gè)類靜態(tài)成員只有一個(gè)數(shù)據(jù)拷
貝。
類的靜態(tài)數(shù)據(jù)成員是在類定義語句被執(zhí)行時(shí)即創(chuàng)建,所以是靜態(tài)生存期,與對(duì)象的創(chuàng)建和注
銷無關(guān)。
定義方法:在類成員定義中加關(guān)鍵字“static”,然后在類外為靜態(tài)數(shù)據(jù)成員分配內(nèi)存空間并初
始化。
調(diào)用方法:內(nèi)部,任何成員函數(shù)都可以直接調(diào)用;外部,用任何一個(gè)該類成員調(diào)用,或者用
類名加“直接調(diào)用。
例:
classcomplex
(
private:
doublereal;
doubleimage;
public:
staticintsum;
voidset(doubler,doublei)
real=r;
image=i;
sum++;〃用靜態(tài)成員統(tǒng)計(jì)set函數(shù)的調(diào)用次數(shù)
)
voiddisplayO
(
cout?real?"+"?image?"i"?endl;
}
);
intcomplex::sum=0;
voidmain()
(
complexx,y;
x.set(l,3);
y.set(3,5);
cout?x.sum;
cout?complex::sum;
)
注:也可以定義靜態(tài)函數(shù)成員。靜態(tài)成員函數(shù)的特點(diǎn)是,不會(huì)自動(dòng)傳遞this指針,所以靜態(tài)
成員函數(shù)一般專用于處理靜態(tài)數(shù)據(jù)成員。
三、友元
在類中可以指定另?個(gè)類或別的函數(shù)為自己的友元。友元和類內(nèi)部成員函數(shù)的訪問權(quán)限相
同,即友元可以訪問類的所有成員。
例:
classcomplex
(
friendvoidset(doubler,doublei,complex*p);〃聲明了一個(gè)友元函數(shù)
friendclassc;〃聲明了類c是類complex的友元
friendvoidb::fl();〃聲明了類b的成員函數(shù)fl是友元函數(shù)
private:
doublereal;
doubleimage;
public:
voiddisplayO
(
cout?real?"+"?image?nin?endl;
)
);
voidset(doubler,doublei,complex*p)
(
p->real=r;
p->image=i;
voidmain()
(
complexx;
set(l,3,&x);
x.display();
)
注意:
1.友元函數(shù)并不是類的一個(gè)成員,而是單獨(dú)的一個(gè)外部函數(shù)。友元函數(shù)要訪問類的成員,
需要利用對(duì)象指針等參數(shù),指定要訪問的是哪個(gè)對(duì)象的成員。
2.如果指定類b是類a的友元類,則類b中的所有成員函數(shù)都可以任意訪問類a的成員。
但是反過來類a并不是類b的友元,不能任意訪問類b的成員。
四、常量成員和對(duì)象成員
類中的數(shù)據(jù)成員是常量或者另?個(gè)類的對(duì)象的情況。
例:
classB
(
ints;
);
classA
(
Bx;
constinty;
);
注意:
定義類的時(shí)候不能給常量成員指定初值,常量成員是屬于對(duì)象的,每個(gè)對(duì)象的同名常量成員
可以取不同的值。
五、構(gòu)造函數(shù)
1.因?yàn)閷?duì)象定義后在外部無法訪問私有的成員,所以用?個(gè)特殊的成員函數(shù),構(gòu)造函數(shù)給
對(duì)象初始化。當(dāng)系統(tǒng)新定義一個(gè)對(duì)象時(shí).,會(huì)自動(dòng)調(diào)用構(gòu)造函數(shù)。
構(gòu)造函數(shù)名字與類名相同,沒有返回值類型,可以重載,應(yīng)設(shè)置為公有權(quán)限。
如果沒有定義任何構(gòu)造函數(shù),系統(tǒng)會(huì)自動(dòng)產(chǎn)生一個(gè)默認(rèn)構(gòu)造函數(shù),這個(gè)默認(rèn)函數(shù)沒有參數(shù)并
且什么也不做。如果自定義了構(gòu)造函數(shù),系統(tǒng)就不會(huì)自動(dòng)產(chǎn)生默認(rèn)構(gòu)造函數(shù),注意這時(shí)不帶
參數(shù)定義對(duì)象可能就會(huì)出錯(cuò)。
例:
classcomplex
(
private:
doublereal;
doubleimage;
public:
complex(doubler,doublei)〃構(gòu)造函數(shù)
(
real=r;
image=i;
)
voidset(doubler,doublei)
(
real=r;
image=i;
)
voiddisplay()
(
cout?real?',+',?image?',i"?endl;
)
);
voidmain()
(
complexx(l,3),y(3,4);〃通過構(gòu)造函數(shù)初始化
complexz;〃錯(cuò)誤,此時(shí)已經(jīng)沒有自動(dòng)生成的無參構(gòu)造函數(shù)了
x.displayO;
y.set(3,5);
y.displayO;
)
注:
構(gòu)造函數(shù)如果要求參數(shù),定義對(duì)象時(shí)必須用括號(hào)加上初始化參數(shù)。構(gòu)造函數(shù)不要求參數(shù),定
義時(shí)對(duì)象名后不加括號(hào)。構(gòu)造函數(shù)的參數(shù)可以帶上默認(rèn)值。
例:
classcomplex
(
private:
doublereal;
doubleimage;
public:
complex(doubler=0,doublei=0)〃構(gòu)造函數(shù)
(
real=r;
image=i;
)
);
voidmain()
(
complexx;〃構(gòu)造函數(shù)默認(rèn)參數(shù),復(fù)數(shù)為0
complexy(3,4);
2.冒號(hào)初始化列表
C++允許構(gòu)造函數(shù)在冒號(hào)后加成員初始化列表,列表中用括號(hào)給出初始化參數(shù)。
初始化列表中列出的數(shù)據(jù)成員初始化的順序,按照類的聲明中這些成員出現(xiàn)的順序進(jìn)行,不
是按照初始化列表中出現(xiàn)的順序。一般初始化列表中的順序應(yīng)和聲明的順序一致。
類的對(duì)象成員,類的常量成員,對(duì)象繼承,引用型的參數(shù),這些情況下都必須使用初始化列
表。對(duì)于有構(gòu)造函數(shù)的數(shù)據(jù)成員,用初始化列表效率較高。
例:
classcomplex
private:
doublereal;
doubleimage;
public:
complex(doubler=0,doublei=O):real(r),image(i){}
);
voidmain()
(
complexx;
complexy(3,4);
例:
classcl
public:
cl(inti=0):a(i){}
inta;
);
classc2
public:
c2(inti=O):t(5),a(b+l),b(i){}
clt;
constintb;
inta;
);
voidmain()
(
c2x,y(3);
cout?x.a?y.a;
)
3.構(gòu)造函數(shù)中開辟動(dòng)態(tài)空間
在類中有一個(gè)指針成員,這個(gè)指針用來掛載動(dòng)態(tài)申請(qǐng)的存儲(chǔ)空間。
例:
classperson
(
private:
char*name;
intage;
public:
person(inta,char*p="nonamen);
voiddisplay()
(
cout?"name:n?name?uage:"?age?endl;
}
);
person::person(inta,char*p):age(a)
(
name=newchar[strlen(p)+l];
strcpy(name,p);
)
voidmain()
(
chart[20];
inta;
personx(18,"tom");
cout?"請(qǐng)輸入名字”;
cin?t;
coutvv"請(qǐng)輸入年齡”;
cin?a;
persony(a,t);
x.displayO;
y.display();
六、析構(gòu)函數(shù)
析構(gòu)函數(shù)用來在對(duì)象注銷之前執(zhí)行一些操作,特別是釋放動(dòng)態(tài)開辟的內(nèi)存空間等操作。
析構(gòu)函數(shù)名字是類名前加沒有返回值類型,一個(gè)類只有一個(gè)析構(gòu)函數(shù),不可以重載,
沒有參數(shù),應(yīng)設(shè)置為公有權(quán)限。
例:
classperson
private:
char*name;
iniage;
public:
person(inta,char*p=nnonamen):age(a)
(
name=newchar[strlen(p)+1];
strcpy(name,p);
)
~person()
(
delete[]name;
)
voiddisplay()
(
cout?uname:"?name?nage:u?age?endl;
七、轉(zhuǎn)換構(gòu)造函數(shù)
1.如果構(gòu)造函數(shù)可以只帶一個(gè)參數(shù),這個(gè)構(gòu)造函數(shù)就是隱式定義的類型轉(zhuǎn)換構(gòu)造函數(shù),可
以把這個(gè)參數(shù)的數(shù)據(jù)類型轉(zhuǎn)換為該類得類型。
定義過轉(zhuǎn)換構(gòu)造函數(shù)后,系統(tǒng)會(huì)在必要時(shí)自動(dòng)調(diào)用進(jìn)行隱式類型轉(zhuǎn)換,包括賦值、表達(dá)式計(jì)
算、參數(shù)傳遞等。
例:
重載復(fù)數(shù)類的構(gòu)造函數(shù)
classcomplex
(
private:
doublereal;
doubleimage;
public:
voidset(doubler,doublei)
(
real=r;
image=i;
)
voiddisplayO
(
cout?real?',+,,?iTnage?',i,,?endl;
complex(doubleredoublei)
real=r;
image=i;
)
complex(doublex):real(x),image(x){}〃轉(zhuǎn)換構(gòu)造函數(shù)
);
voidmain()
(
complexx(2,3);
complexy(4);
y=6;
x.displayO;
y.display();
}
2.顯示定義的轉(zhuǎn)換函數(shù),用operator加類型名,重載成成員函數(shù),無返回值類型??梢园?/p>
對(duì)象轉(zhuǎn)換成其他類型。
例:
classcomplex
(
private:
doublereal;
doubleimage;
public:
voidset(doubleredoublei)
(
real=r;
image=i;
)
voiddisplayO
(
cout?real?"+',?image?,'i"?endl;
)
complex(doubler,doublei):real(r),image(i){)
operatordouble?!ㄞD(zhuǎn)換函數(shù)
(
doublet;
t=real+image;
returnt;
}
);
voidmain()
complexx(2,3);
doublea;
a=x;
cout?a?endl;
x.displayO;
八、拷貝構(gòu)造函數(shù)
1.根據(jù)現(xiàn)有對(duì)象,創(chuàng)建一個(gè)相同的新對(duì)象時(shí),需耍用到拷貝構(gòu)造函數(shù)。
例:
classcomplex
(
private:
doublereal;
doubleimage;
public:
voidset(doubler,doublei)
(
real=r;
image=i;
}
voiddisplayO
(
cout?real?"+"?image?"i"?endl;
)
complex(doubler,doublei)
{
real=r;
image=i;
)
complex(constcomplex&t)〃拷貝構(gòu)造函數(shù),形參是一個(gè)只讀的引用
(
real=t.real;
image=t.image;
)
);
voidmain()
(
complexx(2,3);
complexy(x);〃使用拷貝構(gòu)造函數(shù)
y.display();
除了在定義對(duì)象時(shí)使用拷貝構(gòu)造函數(shù),當(dāng)函數(shù)參數(shù)是對(duì)象時(shí),實(shí)參對(duì)象傳給形參會(huì)調(diào)用拷貝
構(gòu)造函數(shù);當(dāng)函數(shù)返回值是一個(gè)對(duì)象時(shí),會(huì)利用拷貝構(gòu)造函數(shù)產(chǎn)生一個(gè)臨時(shí)對(duì)象表示函數(shù)返
回值。這也是為什么拷貝構(gòu)造函數(shù)的參數(shù)是對(duì)象的引用。
由于對(duì)象的創(chuàng)建和注銷都耗費(fèi)系統(tǒng)資源,一般函數(shù)參數(shù)和函數(shù)返回值都用對(duì)象的引用。
為了保證函數(shù)調(diào)用的成功,如果沒有自定義拷貝構(gòu)造函數(shù),系統(tǒng)會(huì)創(chuàng)建一個(gè)默認(rèn)拷貝構(gòu)造函
數(shù),它的功能是復(fù)制參數(shù)對(duì)象的所有數(shù)據(jù)成員到新建對(duì)象。
2.深拷貝和淺拷貝
當(dāng)對(duì)象中含有指針和動(dòng)態(tài)開辟的內(nèi)存空間時(shí),可以看到簡單的數(shù)據(jù)復(fù)制不能正確的拷貝對(duì)
象。
例:
classperson
(
private:
char*name;
intage;
public:
person(inta,char*p=,'nonameM);
person(constperson&t);
voiddisplayO
(
cout?,'name:"?name?,'age:"?age?endl;
}
voidsetname(char*p)
(
delete[]name;
name=newchar[strlen(p)+l];
strcpy(name,p);
)
~person()
(
delete[]name;
)
);
person::person(inta,char*p):age(a)
(
name=newcharfstrlen(p)+l];
strcpy(name,p);
}
person::person(constperson&t):age(t.age)
(
name=newchar[strlen()+1];〃給新對(duì)象開辟內(nèi)存空間
strcpy(name,);
)
voidmain()
personx(18,ntomn);
persony(x);
y.setname(nmikeM);
x.displayO;
y.display();
)
簡單的數(shù)據(jù)復(fù)制稱為淺拷貝,帶有動(dòng)態(tài)申請(qǐng)空間和指針的數(shù)據(jù)復(fù)制稱為深拷貝。系統(tǒng)自動(dòng)生
成的拷貝構(gòu)造函數(shù)只能實(shí)現(xiàn)淺拷貝。
九、成員函數(shù)重載
例:person類重載set函數(shù)
classperson
(
private:
char*name;
intage;
public:
person(inta,char*p=Hnoname");
person(constperson&t);
~person()
(
deletedname;
)
voiddisplay()
(
cout?"name:n?name?uage:"?age?endl;
)
voidset(char*p)〃參數(shù)是字符串,改名字
(
delete[]name;
name=newchar[strlen(p)+l];
strcpy(name,p);
)
voidset(inta)〃參數(shù)是數(shù)字,改年齡
{
age=a;
}
voidset(inta,char*p)〃改名字年齡
{
set(p);
set(a);
)
);
person::person(inta,char*p):age(a)
(
name=newchar[strlen(p)+l];
strcpy(name,p);
)
person::person(constperson&t):age(t.age)
(
name=newchar[strlen()+1];
strcpy(name,);
)
voidmain()
(
personx(18,utom");
persony(x);
y.set("m汰e");
x.set(20/abcn);
x.display();
y.displayO;
)
十、運(yùn)算符重載
C++中的運(yùn)算符能夠以函數(shù)重載的方式重新定義,以擴(kuò)充運(yùn)算符的功能。運(yùn)算符的函數(shù)形式
是運(yùn)算符前加“operator、運(yùn)算符可以被重載為類的成員函數(shù)或者友元函數(shù)。
例:復(fù)數(shù)類加法
classcomplex
(
private:
doublereal;
doubleimage;
public:
voiddisplay()
(
cout?real?',+,,?image?"i,'?endl;
)
complex(doubler=0,doublei=O):real(r),image(i){}
complexoperator+(complex&a)〃重載加法運(yùn)算
(
complext;
t.real=real+a.real;
t.image=image+a.image;
returnt;
voidmain()
complexx(2,3),y(4,5),z;
z=x+y;
z.displayO;
)
因?yàn)榘鸭臃ㄟ\(yùn)算定義為類的成員函數(shù),所以只帶了?個(gè)參數(shù)表示兩個(gè)加數(shù)中的一個(gè),另個(gè)
加數(shù)是調(diào)用這個(gè)成員函數(shù)的對(duì)象。參數(shù)用引用省去了創(chuàng)建和注銷對(duì)象的過程。
例:重載成友元
classcomplex
(
friendcomplexoperator+(complex&a,complex&b);
private:
doublereal;
doubleimage;
public:
voiddisplayO
(
cout?real?"+',?image?,'i,,?endl;
)
complex(doubler=0,doublei=O):real(r),image(i){}
);
complexoperator+(complex&a,complex&b)〃重載力口法運(yùn)算
(
complext;
t.real=a.real+b.real;
t.image=a.image+b.image;
returnt;
)
voidmain()
(
complexx(2,3),y(4,5),z;
z=x+y;
z.display();
)
運(yùn)算符重載有一定限制,不是所有運(yùn)算法都可以重載成友元,也不是所有運(yùn)算符都可以重載,
運(yùn)算符重載也不能改變結(jié)合性和優(yōu)先級(jí),參數(shù)個(gè)數(shù)等。
十一、使用構(gòu)造函數(shù)的其他格式
1.當(dāng)構(gòu)造函數(shù)的參數(shù)只有一個(gè)時(shí).,用“?!焙陀?=”等效,調(diào)用的都是構(gòu)造函數(shù)。
例:
classcomplex
(
private:
doublereal;
doubleimage;
public:
voiddisplay()
(
cout?real?"+"?image?"i"?endl;
)
complex(doubler)
(
real=r;
image=r;
)
complex(constcomplex&t)
{
real=t.real;
image=t.image;
}
);
voidmain()
(
complexx=2;
complexy=x;
y.display();
)
2.構(gòu)造函數(shù)也可以直接調(diào)用,會(huì)產(chǎn)生一個(gè)臨時(shí)對(duì)象作為返回值。
例:
classcomplex
(
private:
doublereal;
doubleimage;
public:
voiddisplay()
(
cout?real?"+',?image?,'i,'?endl;
)
complex(doubler,doublei)
(
real=r;
image=i;
)
complex(constcomplex&t)
real=t.real;
image=t.image;
voidmain()
(
complexx(l,2);
x=complex(4,5);//除了調(diào)用構(gòu)造函數(shù),還調(diào)用了賦值運(yùn)算符
x.displayO;
)
例:
classcomplex
(
private:
doublereal;
doubleimage;
public:
voiddisplay()
(
cout?real?"+',?image?,'i,,?endl;
)
complex(doubler=0,doublei=O):real(r),image(i){}
complexoperator+(complex&a)〃重載加法運(yùn)算
(
returncomplex(real+a.real,image+a.image);
)
);
voidmain()
(
complexx(2,3),y(4,5),z;
z=x+y;
z.displayO;
I
十二、典型運(yùn)算符重載
1.賦值運(yùn)算符
賦值運(yùn)算只能被重載為成員函數(shù)。賦值運(yùn)算符重載不能被繼承。如果不定義賦值運(yùn)算符重載,
系統(tǒng)在需要時(shí)會(huì)自動(dòng)生成一個(gè),效果是實(shí)現(xiàn)對(duì)象數(shù)據(jù)成員的淺拷貝。
例:
classperson
(
private:
char*name;
intage;
public:
person(inta=20,char*p="noname");
voiddisplayO
{
cout?uname:n?name?uage:u?age?endl;
)
-person()
(
delete[]name;
)
person&operator=(person&t)
{
if(this==&t)return*this;
age=t.age;
if(name)
(
delete[]name;
name=NULL;
}
if()
(
name=newchar[strlen()+1];
strcpy(name,);
)
return*this;
)
);
person::person(inta,char*p):age(a)
(
name=newchar[strlen(p)+l];
strcpy(name,p);
)
voidmain()
(
personx(18,"tom");
persony;
y=x;
x.displayO;
y.display();
)
注意:賦值運(yùn)算符和拷貝構(gòu)造函數(shù)是兩個(gè)不同的函數(shù),賦值運(yùn)算符一定要考慮賦值號(hào)兩邊是
同一個(gè)對(duì)象的情況,還要清理左邊的對(duì)象。賦值運(yùn)算符的返回值是一個(gè)對(duì)象引用,即被賦值
的對(duì)象本身。
2.自增運(yùn)算符重載
因?yàn)樽栽鲞\(yùn)算分前綴后綴兩種情況,重載時(shí),后綴運(yùn)算視為雙目運(yùn)算,第二個(gè)參數(shù)是int型
的0?
前綴++的返回值是左值,后綴++的返回值是右值。
例:復(fù)數(shù)類
classcomplex
(
private:
doublereal;
doubleimage;
public:
voidset(doubleredoublei)
(
real=r;
image=i;
)
voiddisplayO
(
cout?real?"+',?image?,'i,,?endl;
)
complex(doubler=0,doublei=O):real(r),image(i){}
complex&operator++()〃前綴++
(
real++;
image++;
return%his;
)
complexoperator++(int)〃后綴++
(
complext=*this;〃用到了拷貝構(gòu)造函數(shù)
real++;
image++;
returnt;
)
);
voidmain()
(
complexx(2,3),y(l,l);
x=y++;
x.display();
y.display();
++y;
y.displayO;
例:重載為友元函數(shù)
classcomplex
(
friendcomplex&operator++(complex&a);
friendcomplexoperator++(complex&a,int);
private:
doublereal;
doubleimage;
public:
voidset(doubleredoublei)
(
real=r;
image=i;
)
voiddisplayO
(
cout?real?',+',?image?,'i"?endl;
)
complex(doubler=0,doublei=O):real(r),image(i){}
);
complex&operator++(complex&a)〃前綴++
(
a.real++;
a.image++;
returna;
)
complexoperator++(complex&a,int)〃后綴++
(
complext=a;
a.real++;
a.image++;
returnt;
I
voidmain()
(
complexx(2,3),y(l,l);
x=y++;
x.display();
y.display();
++y;
y.display();
}
重載為友元就多了一個(gè)參數(shù)。
第八章繼承與派生
8.1繼承概念
一、繼承概念和派生類定義
繼承就是在已有的類基礎(chǔ)匕添加新成員,構(gòu)成一個(gè)新的類,新類中的成員包括新加成員和
繼承過來的成員。
被繼承的類稱為基類、父類,新類稱為派生類、子類。
定義派生類時(shí),用冒號(hào)表示基類,用public、private、protected表示公有、私有、保護(hù)三種
繼承方式。不寫繼承方式時(shí),用class定義的派生類默認(rèn)私有繼承,用struct定義的派生類
默認(rèn)公有繼承。
例:
#include<iostream>
usingnamespacestd;
classcircle
(
public:
doubler;
doublearea()
{
returnr*r*3.14159;
}
voidset(doublea)
{
r=a;
}
);
classcylinder:publiccircle
(
public:
doubleh;
doublevolume()
(
returnr*r*3.14159*h;
)
voidsetc(doublea,doubleb)
(
r=a;
h=b;
)
);
voidmain()
circlex;
x.set(3);
cout?x.area()?endl;
cylindery;
y.setc(3,5);
cout?y.volume()?endl;
cout?y.area()?endl;
圓柱類公有繼承自圓類,圓柱類擁有圓類的所有成員,外加自己新定義的成員。
二、類成員的訪問屬性
1.類成員訪問屬性分為四種
定義類成員時(shí),publicprotectedprivate表示公有、保護(hù)、私有三種訪問權(quán)限。
類內(nèi)成員函數(shù)可以訪問本類的私有、保護(hù)、公有成員,類外函數(shù)通過對(duì)象只能訪問公有成員。
派生類新加成員函數(shù)不可以訪問原基類的私有成員,但是從基類繼承的成員函數(shù)可以。
類成員訪問屬性分為四種:公有、保護(hù)、私有、隱藏(基類私有成員)。
2.繼承方式對(duì)成員訪問屬性的影響
不論采用何種繼承方式,基類私有成員到了派生類中一定變成了隱藏屬性,以下討論基類的
公有和保護(hù)成員。
公有繼承:基類成員的訪問屬性不變。
保護(hù)繼承:基類成員訪問屬性全部變成保護(hù)。
私有繼承:基類成員訪問屬性全部變成私有。
注意,派生類中的隱藏成員并不是不存在,隱藏成員是通過基類的公有成員函數(shù)這個(gè)接口來
訪問的。
#include<iostream>
usingnamespacestd;
classM
private:
intc;
protected:
intb;
public:
inta;
voidset(intx,inty,intz)
b=y;
voiddisplayO
cout?a?',?b?',?c?endl;
classN:publicM
(
public:
intd;
);
voidmain()
(
Nx;
x.set(l,2,3);
x.d=4;
x.displayO;
cout?x.a?x.d?endl;
)
建議:;在設(shè)計(jì)類時(shí)盡量用私有成員,私有成員對(duì)派生類是隱藏的,派生類中只考慮基類的
接口函數(shù)即可;繼承方式盡量用公有,這樣不會(huì)改變基類成員的訪問屬性。
三、多繼承和多重繼承
如果派生類從多個(gè)基類繼承而來,叫做多繼承。
如果類A派生出類B,類B又派生出類C,叫做多重繼承。
繼承必須單向,不允許構(gòu)成環(huán)形結(jié)構(gòu)。
四、基類成員二義性處理
如果派生類新定義的成員,和從基類繼承過來的可訪問成員名字重復(fù),這時(shí)默認(rèn)訪問派生類
新定義的成員。如果是多重繼承,幾個(gè)基類中有重名成員,優(yōu)先訪問繼承樹中距離近的成員。
如果要訪問指定的某個(gè)基類成員,在成員名前加上定義它的基類名和"::“。
在派生類中定義基類的同名成員,不會(huì)形成函數(shù)重載,而是把基類成員重新定義和修正,使
之適應(yīng)派生出來的新類。
重載是overload,意為超載。重定義是覆蓋override,重定義的成員一般要求參數(shù)表與老版
本保持一致。
例:
#include<iostream>
usingnamespacestd;
classcircle
(
private:
doubler;
public:
doublearea()
returnr*r*3.14159;
doublecircumference()
(
return2*r*3.14159;
)
voidset(doublea)
(
r=a;
)
);
classcylinder:publiccircle
(
private:
doubleh;
public:
doublevolume()
(
returncircle::area()*h;
)
doublearea()
(
returncircle::area()*2+circumference()*h;
)
voidset(doublea,doubleb)
(
circle::set(a);
h=b;
)
);
voidmain()
(
circlex;
x.set(3);
cout?x.area()?endl;
cylindery;
y.set(3,5);
cout?y.volume()?endl;
cout?y.area()?endl;
cout?y.circle::area()?endl;
}
例:
#include<iostream>
usingnamespacestd;
structA"struct定義的類默認(rèn)公有成員,默認(rèn)公有繼承
{inta;};
structB:A
{intb;};
structC:B
{inta;};
voidmain()
(
Ct;
t.A::a=l;
cout?t.B::a;
t.B::a=5;
cout?t.A::a;
)
運(yùn)算結(jié)果:1
5
注意:只要不產(chǎn)生二義性,這里用類A的派生類類B調(diào)用成員a也可以。調(diào)用被覆蓋了的
基類成員,最好用該成員第一次定義所在類的類名,即用A來調(diào)用。
五、特殊成員的繼承特性
1.靜態(tài)成員
基類的靜態(tài)成員可以被繼承,基類和派生類將共享同一個(gè)靜態(tài)成員。
2.友元
基類的友元并不會(huì)成為派生類的友元,但是基類成員如果是別的類的友元,派生后仍保留友
元權(quán)限。
六、派生類的構(gòu)造和析構(gòu)
構(gòu)造函數(shù)和析構(gòu)函數(shù)都不能繼承。
創(chuàng)建對(duì)象時(shí),通過初始化列表,派生類調(diào)用基類的構(gòu)造函數(shù)完成初始化。
初始化列表只是初始化參數(shù)的分配表,它的順序和實(shí)際初始化的順序無關(guān)。系統(tǒng)先自動(dòng)調(diào)用
基類構(gòu)造函數(shù)初始化基類,再初始化派生類的新成員。
如果初始化列表中沒有基類構(gòu)造函數(shù),系統(tǒng)仍然會(huì)自動(dòng)調(diào)用基類構(gòu)造函數(shù),但是不給參數(shù)。
注銷對(duì)象時(shí),系統(tǒng)在執(zhí)行完派生類析構(gòu)函數(shù)后自動(dòng)調(diào)用基類的析構(gòu)函數(shù),基類析構(gòu)函數(shù)名不
出現(xiàn)。先注銷派生類新加成員,再調(diào)用基類析構(gòu)函數(shù)注銷基類成員。
例:
classA
(
public:
inta;
A(inti):a(i)
cout?"A"?'
~A()
(
cout?"~A"?'
}
);
classB:publicA
(
public:
inib;
B(inti,intj):b(j),A(i)
{
cout?"B"?'
}
~B()
{
cout?"~B"?'
}
);
classC:publicB
(
public:
intc;
C(inti,intj,intk):c(k),B(i,j)
{
cout?"C"?'
}
~C()
{
cout?"~C"?'
)
);
voidf()
(
Cx(2,3,4);
cout?x.a?x.b?x.c?endl;
)
voidmain()
f();
多重繼承情況下,系統(tǒng)只是調(diào)用自己上一層的父類的構(gòu)造和析構(gòu)函數(shù),并不會(huì)調(diào)用祖父類的。
例:
classA
(
public:
inta;
A(inli):a(i)
(
cout?"A"?'
)
~A()
{
cout?"-A"?'
)
};
classB
(
public:
intb;
B(inti):b(i)
{
cout?"B"?'
}
~B()
{
cout?"~B"?'
classC:publicB,publicA
(
public:
intc;
C(inti,intj,intk):B⑴,A①,c(k)
{
cout?"C"?'
)
~C()
(
cout?"~C"?'
}
};
voidf()
cx(2,3,4);
cout?x.a?x.b?x.c?endl;
)
voidmain()
(
f();
)
七、虛基類和虛繼承
1.在復(fù)雜的樹形繼承關(guān)系中,有時(shí)會(huì)形成數(shù)據(jù)冗余。
例:
classA
{inta;};
classB:A
{intb;};
classC:A,B
{intc;};
這種情況下,明顯有兩份A類拷貝,數(shù)據(jù)冗余。這種繼承方式大部分C++編譯器會(huì)報(bào)錯(cuò)。
例:
classA
{inta;};
classBI:A
{intx;};
classB2:A
{inty;};
classC:B,C
{intc;};
此時(shí)D類的對(duì)象中有兩份A類拷貝。這時(shí)系統(tǒng)不會(huì)報(bào)錯(cuò),可以通過Bl::a和B2::a分別調(diào)用
兩個(gè)成員a。注意不能用A::a。
例:
classA
(
public:
inta;
A(inti):a(i){)
);
classBkpublicA
(
public:
intx;
Bl(inti,intj):A(i),x(j){)
);
classB2:publicA
public:
inty;
B2(inti,intj):A(i),y(j){)
);
classC:publicBl,publicB2
(
public:
intc;
C(inti,intj,intk,intm,intn):B1(ij),B2(m,n),c(k){}
);
voidmain()
(
Ct(l,2,3,4,5);
cout?t.B1::a?t.B2::a?t.x?t.y?t.c;
)
2.虛繼承
虛繼承專門解決上述繼承方式下(菱形繼承)的數(shù)據(jù)冗余,虛繼承將重復(fù)的基類拷貝合并成
一個(gè)。
加了virtual關(guān)鍵字的繼承方式叫做虛繼承。
例:
classA
{inta;};
classB1:virtualpublicA
{intx;};
classB2:virtualpublicA
{inty;};
classC:B1,B2
{intb;};
此時(shí)類Bl和B2虛繼承了類A,類A是類Bl和類B2的虛基類,或說Bl和B2得到的類A
拷貝是一個(gè)虛的基類拷貝。并不是類A就是虛基類,如果一個(gè)類X以一般方式繼承了類A,
類A就是類X的“實(shí)”基類。
虛的基類拷貝在多重繼承樹中向下傳遞(以一般的繼承方式),不管傳遞多少代,仍然是虛
的。類C從B1和B2得到的類A拷貝就仍然是一個(gè)虛的類A拷貝。
從不同父類多次繼承的同一虛基類,只會(huì)產(chǎn)生一份類拷貝。此時(shí)父類對(duì)虛基類的初始化失效
(因?yàn)槎鄠€(gè)父類中包含多次初始化,但是類拷貝只有一個(gè)),派生類直接調(diào)用虛基類的構(gòu)造
函數(shù)進(jìn)行初始化。
例:
classA
(
public:
inta;
A(inti):a(i){)
classB1:virtualpublicA
public:
intx;
Bl(inti,intj):A(i),x(j){)
);
classB2:publicvirtualA
(
public:
inty;
B2(inti,intj):A(i),yG){}
);
classC:publicB1,publicB2
(
public:
intc;
C(inti,intj,intm,intn):A(i),B1(7,j),B2(8,m),c(n){}
);
voidmain()
(
Ct(l,2,3,4);
cout?t.a?t.x?t.y?t.c;
8.2多態(tài)
一、派生類和基類的關(guān)系
i.派生類是由基類添加新成員而產(chǎn)生的基類的進(jìn)一步細(xì)分?;愂强傤愋?,派生類是子類
型,所以派生類對(duì)象也是屬于基類這個(gè)總類型的。
從多個(gè)基類繼承而來的派生類屬于交叉類型,可以認(rèn)為是基類的組合。多繼承的派生類是它
的任何一個(gè)基類的子類型。
例:
基類humen類,派生類student類、teacher類,顯然任何一個(gè)student和teacher也應(yīng)該是humen
類的。
基類“自然科學(xué)”,派生類“物理”、“化學(xué)”,“物理”“化學(xué)”派生出“物理化學(xué)物理化學(xué)是交
叉學(xué)科,既是物理學(xué)的分支,又是化學(xué)的分支。
2.派生類對(duì)象也屬于基類這個(gè)總類型,所以派生類對(duì)象總是可以當(dāng)做基類對(duì)象,把派生類
對(duì)象寫在基類對(duì)象的位置不會(huì)報(bào)告類型不匹配錯(cuò)誤。此時(shí)忽略派生類新加成員,只考慮繼承
來的基類成員。
把派生類對(duì)象直接當(dāng)做基類對(duì)象來用,類似于把整數(shù)當(dāng)做實(shí)數(shù)來用。
a.派生類的地址可以賦值給基類指針,派生類對(duì)象可以用來初始化基類引用。此時(shí)通過基
類指針和基類引用,訪問的是派生類對(duì)象中從基類繼承過去的那部分成員。
b.用基類對(duì)象、基類指針、基類引用作參數(shù)的函數(shù),也可以用派生類的相應(yīng)參數(shù)。即處理
基類對(duì)象的函數(shù)也可以處理派生類對(duì)象中繼承自基類的部分成員。
c.派生類對(duì)象可以賦值給基類對(duì)象,調(diào)用基類的賦值運(yùn)算符重我。派生類對(duì)象可以用來初
始化基類對(duì)象,調(diào)用基類的拷貝構(gòu)造函數(shù)。
例:
classperson
(
private:
charname[20];
intage;
public:
voiddisplayO
(
cout?Hname:H?name?",'?',age:,,?age?endl;
)
intgetage()
(
returnage;
)
person(char*p,inta):age(a)
{
strcpy(name,p);
)
person&operator=(person&t)
(
if(this==*t)return*this;
age=t.age;
strcpy(name,p);
return*this;
)
);
classstudent:publicperson
(
private:
intscore;
public:
voiddisplayO
(
cout?"score:,'?score<<Hu;
person::display();
student(char*p,inta,intb):person(p,a),score(b){}
);
voidf(person&t)
(
inta=t.getage();
if(a<30)
cout?Hyoungboy”;
else
cout?"aman
t.displayO;
)
voidmain()
(
personx(utom",32);
studenty(nmike",18,80);
f(x);
f(y);
x.displayO;
y.display();
x=y;
x.displayO;
)
例:派生類的賦值運(yùn)算符
classperson
(
private:
charname[20J;
intage;
public:
voiddisplayO
(
cout?"name:',?name?H,,?"age:"?age?endl;
)
intgetage()
(
returnage;
)
person(char*p,inta):age(a)
(
strcpy(name,p);
person&operator=(person&t)
if(this==&t)return*this;
age=t.age;
strcpy(name,);
return*this;
);
classstudent:publicperson
(
private:
intscore;
public:
voiddisplayO
(
cout?nscore:n?score?n
person::display();
}
student(char*p,inta,intb):person(p,a),score(b){}
student&operator=(student&t)
if(this==&t)retum*this;
operator=(t);
score=t.score;
return*this;
或者定義為
student&operator=(student&t)
if(this==&t)retum九his;
static_cast<person&>(*this)=t;
*(static_cast<person*>(this))=t;
score=t.score;
return*this;
)
static_cast是c++U」的強(qiáng)制類型轉(zhuǎn)換格式。
3.對(duì)于針對(duì)基類的代碼來說,一個(gè)對(duì)象不管是基類對(duì)象還是派生類對(duì)象,都是用同樣方法
處理的,派生類是基類定義的延續(xù),或者說詳細(xì)定義過的基類。
處理基類的函數(shù)也可以處理派生類,但是這時(shí)派生類的新成員不能使用了。虛函數(shù)和動(dòng)態(tài)多
態(tài)正是為了解決這個(gè)問題。
1.多態(tài)概念
多態(tài)指不同的對(duì)象對(duì)同一消息會(huì)作出不同的反應(yīng)。程序設(shè)計(jì)中的消息指的就是函數(shù)調(diào)用,多
態(tài)指的是不同對(duì)象調(diào)用同一個(gè)函數(shù)名,實(shí)際執(zhí)行了不同的代碼。
多態(tài)分為靜態(tài)多態(tài)和動(dòng)態(tài)多態(tài),又叫靜態(tài)聯(lián)編和動(dòng)態(tài)聯(lián)編。靜態(tài)多態(tài)通過函數(shù)重載實(shí)現(xiàn),動(dòng)
態(tài)多態(tài)由虛函數(shù)實(shí)現(xiàn)。
2.虛函數(shù)
虛函數(shù)是用virtual關(guān)鍵字修飾的類的非私有成員函數(shù)。私有成員是基類專用派生類隱藏的,
不能定義成虛函數(shù)。
虛函數(shù)在繼承樹中派生下去仍然是虛函數(shù),在派生類中重新定義虛函數(shù)時(shí)不管加不加
virtual,重新定義的同名函數(shù)也仍然是虛函數(shù)。
虛函數(shù)的重新定義要求函數(shù)參數(shù)表和返回值都保持不變,否則即使加了virtual也不會(huì)是虛
函數(shù)。
虛函數(shù)不能內(nèi)聯(lián),即使把虛函數(shù)定義寫在類內(nèi),它也不會(huì)是內(nèi)聯(lián)函數(shù)。
當(dāng)把一個(gè)基類指針指向派生類對(duì)象時(shí),或者把一個(gè)基類引用綁定一個(gè)派生類對(duì)象時(shí),利用基
類指針或基類引用調(diào)用虛成員函數(shù),調(diào)用的不是基類中定義的老版本,而是派生類中重新定
義的最新版本。
例:
classperson
(
private:
charname[20];
intage;
public:
virtualvoiddisplayO
(
cout?nname:"vvname<<""vv"age:"vvagevvendl;
)
intgetage()
(
returnage;
)
person(char*p,inta):age(a)
(
strcpy(name,p);
)
);
classstudent:publicperson
(
private:
intscore;
public:
voiddisplayO
cout?nscore:n?score?Mu;
person::display();
)
student(char*p,inta,intb):person(p,a),score(b){}
)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 青少年學(xué)生的營養(yǎng)與發(fā)育問題研究
- 電力工程中用電器件的安全保障措施
- 現(xiàn)代家居風(fēng)格下的個(gè)性化定制家具設(shè)計(jì)探索
- 家禽免疫系統(tǒng)及其生理功能的奧秘
- 學(xué)生主導(dǎo)的決策體驗(yàn)提升職業(yè)規(guī)劃能力
- 評(píng)估學(xué)校道德教育效果的學(xué)生反饋機(jī)制
- 2025年濟(jì)南貨運(yùn)從業(yè)資格證考試題技巧及答案
- 跨學(xué)科合作在小學(xué)心理健康教育中的實(shí)踐
- 二零二五年度房屋買賣合同解除及裝修補(bǔ)償協(xié)議
- 2025年度智能貸款產(chǎn)品居間服務(wù)合同
- 輸變電工程監(jiān)督檢查標(biāo)準(zhǔn)化清單-質(zhì)監(jiān)站檢查
- 【超星學(xué)習(xí)通】馬克思主義基本原理(南開大學(xué))爾雅章節(jié)測(cè)試網(wǎng)課答案
- 2024年中國工業(yè)涂料行業(yè)發(fā)展現(xiàn)狀、市場前景、投資方向分析報(bào)告(智研咨詢發(fā)布)
- 化工企業(yè)重大事故隱患判定標(biāo)準(zhǔn)培訓(xùn)考試卷(后附答案)
- 工傷賠償授權(quán)委托書范例
- 食堂餐具炊具供貨服務(wù)方案
- 2024化工園區(qū)危險(xiǎn)品運(yùn)輸車輛停車場建設(shè)規(guī)范
- 自然科學(xué)基礎(chǔ)(小學(xué)教育專業(yè))全套教學(xué)課件
- 華為客服制度
- 醫(yī)美面部抗衰老注射項(xiàng)目培訓(xùn)課件
- 小學(xué)語文閱讀教學(xué)落實(shí)學(xué)生核心素養(yǎng)方法的研究-中期報(bào)告
評(píng)論
0/150
提交評(píng)論