一、概念
創(chuàng)新互聯(lián)2013年開創(chuàng)至今,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務(wù)公司,擁有項(xiàng)目成都網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì)網(wǎng)站策劃,項(xiàng)目實(shí)施與項(xiàng)目整合能力。我們以讓每一個(gè)夢(mèng)想脫穎而出為使命,1280元循化做網(wǎng)站,已為上家服務(wù),為循化各地企業(yè)和個(gè)人服務(wù),聯(lián)系電話:028-86922220
多態(tài)是面向?qū)ο蟪绦蛟O(shè)計(jì)的三大特征之一。封裝性是基礎(chǔ),繼承性是關(guān)鍵,多態(tài)性是補(bǔ)充,而多態(tài)又存在于繼承的環(huán)境之中。多態(tài)性的含義就是多種狀態(tài)。C++語言中支持兩種多態(tài)性。一種是函數(shù)重載和運(yùn)算符重載,又被稱為靜態(tài)多態(tài),另一種是動(dòng)態(tài)聯(lián)編和虛函數(shù),被稱為動(dòng)態(tài)多態(tài)。在這里主要討論第一種和第二種的虛函數(shù)。
1.函數(shù)重載
函數(shù)重載簡(jiǎn)單的說就是給一個(gè)函數(shù)名多個(gè)含義。C++語言中允許在相同的作用域內(nèi)以相同的名字定義幾個(gè)不同實(shí)現(xiàn)的函數(shù)。定義這種重載函數(shù)時(shí)要求函數(shù)的參數(shù)或者至少有一個(gè)類型不同,或者個(gè)數(shù)不同,或者順序不同。參數(shù)個(gè)數(shù)和類型,順序都相同,僅返回值不同的重載函數(shù)是非法的。因?yàn)榫幾g程序在選擇相同名字的重載函數(shù)是僅考慮函數(shù)參數(shù)列表,即要根據(jù)函數(shù)參數(shù)列表中的參數(shù)個(gè)數(shù)、參數(shù)類型或參數(shù)順序的差異進(jìn)行選擇。
舉例:string類的構(gòu)造函數(shù)重載(編譯環(huán)境:VS2013)
#define _CRT_SECURE_NO_WARNINGS 1 #includeusing namespace std; #include class String { public: String(char *s) { length = strlen(s); ps = new char[length + 1]; strcpy(ps, s); } String(string &s) { length = s.length; ps = new char[length + 1]; strcpy(ps, s.ps); } String(int size = 20) { length = size; ps = new char[length + 1]; *ps = '\0'; } ~String() { delete ps; } int getlen() { return length; } void print() { cout << ps << endl; } private: char* ps; int length; }; int main() { String str1("String"); str1.print(); cout << str1.getlen() << endl; char *ps1 = "String Pionter"; String str2(ps1); String str3(str2); str3.print(); cout << str3.getlen() << endl; system("pause"); return 0; }
String類的構(gòu)造函數(shù)被重載了三次,
str1("String")調(diào)用構(gòu)造函數(shù)String(char *s);
str2(ps1)調(diào)用構(gòu)造函數(shù)String(char *s);
str3(str2)調(diào)用構(gòu)造函數(shù)String(String);
2.運(yùn)算符重載
運(yùn)算符重載重載就是賦予已有的運(yùn)算符多重定義,使它具多種多種功能。
定義方法:類名 operator運(yùn)算符(參數(shù)列表){ }
下面的運(yùn)算符在C++中允許重載:
算數(shù)運(yùn)算符: +, -, *, /, %, ++, --
位操作運(yùn)算符: &,|, ~, ^, <<,>>
邏輯運(yùn)算符: !, &&, ||
比較運(yùn)算符: <, >, <=, >=, ==, !=
賦值運(yùn)算符: =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=
其它運(yùn)算符: [], (), ->, ', new, delete, new[], delete[]
下列運(yùn)算符不允許重載:
·,·*, ::,?
使用運(yùn)算符重載的注意:
用戶重新定義運(yùn)算符時(shí),不改變?cè)\(yùn)算符的優(yōu)先級(jí)和結(jié)合性。不改變運(yùn)算符的操作數(shù)個(gè)數(shù)和語法結(jié)構(gòu),單目運(yùn)算符只能重載為單目運(yùn)算符,雙目運(yùn)算符只能重載雙目運(yùn)算符。
重載運(yùn)算符不能有二義性。
運(yùn)算符重載舉例:
//運(yùn)算符重載 #includeusing namespace std; class Complex { //friend Complex operator+(Complex c1, Complex c2); public: Complex(double real = 0.0, double p_w_picpath = 0.0) : _real(real) , _p_w_picpath(p_w_picpath) {} Complex(const Complex& c) : _real(c._real) , _p_w_picpath(c._p_w_picpath) {} Complex operator+(const Complex& c1) { return Complex(_real + c1._real, _p_w_picpath + c1._p_w_picpath); } Complex operator-(const Complex& c1) { return Complex(_real - c1._real, _p_w_picpath - c1._p_w_picpath); } Complex operator*(const Complex& c1) { return Complex(_real*c1._real - _p_w_picpath*c1._p_w_picpath, _real*c1._p_w_picpath + _p_w_picpath*c1._real); } Complex operator/(const Complex& c1) { return Complex((_real*c1._real + _p_w_picpath*c1._p_w_picpath) / (c1._p_w_picpath*c1._p_w_picpath + c1._real*c1._real), (_p_w_picpath*c1._real - _real*c1._p_w_picpath) / (c1._p_w_picpath*c1._p_w_picpath + c1._real*c1._real)); } Complex& operator+=(const Complex& c1) { _real = _real + c1._real; _p_w_picpath = _p_w_picpath + c1._p_w_picpath; return *this; } Complex& operator-=(const Complex& c1) { _real = _real - c1._real; _p_w_picpath = _p_w_picpath - c1._p_w_picpath; return *this; } Complex& operator*=(const Complex& c1) { double tmp = _real; _real = _real*c1._real - _p_w_picpath*c1._p_w_picpath; _p_w_picpath = tmp*c1._p_w_picpath + _p_w_picpath*c1._real; return *this; } Complex& operator/=(const Complex& c1) { double tmp = _real; _real = (_real*c1._real + _p_w_picpath*c1._p_w_picpath) / (c1._p_w_picpath*c1._p_w_picpath + c1._real*c1._real); _p_w_picpath = (_p_w_picpath*c1._real - tmp*c1._p_w_picpath) / (c1._p_w_picpath*c1._p_w_picpath + c1._real*c1._real); return *this; } // 只比較實(shí)部 bool operator<(const Complex& c) { if (_real (const Complex& c) { if (_real>c._real) { return true; } else { return false; } } bool operator<=(const Complex& c) { if ((_real 對(duì)復(fù)數(shù)的四則運(yùn)算,++,--(前置,后置)等進(jìn)行了重載。
3.虛函數(shù)
使用virtual關(guān)鍵字修飾函數(shù)時(shí),指明該函數(shù)為虛函數(shù),派生類需要重新實(shí)現(xiàn),編譯器將實(shí)現(xiàn)動(dòng)態(tài)綁定。
總結(jié):
1、派生類重寫基類的虛函數(shù)實(shí)現(xiàn)多態(tài),要求函數(shù)名、參數(shù)列表、返回值完全相同。(協(xié)變除外)
2、基類中定義了虛函數(shù),在派生類中該函數(shù)始終保持虛函數(shù)的特性。
3、只有類的成員函數(shù)才能定義為虛函數(shù),靜態(tài)成員函數(shù)不能定義為虛函數(shù)。
4、如果在類外定義虛函數(shù),只能在聲明函數(shù)時(shí)加virtual關(guān)鍵字,定義時(shí)不用加。
5、構(gòu)造函數(shù)不能定義為虛函數(shù),雖然可以將operator=定義為虛函數(shù),但最好不要這么做,使用時(shí)容易混淆
6、不要在構(gòu)造函數(shù)和析構(gòu)函數(shù)中調(diào)用虛函數(shù),在構(gòu)造函數(shù)和析構(gòu)函數(shù)中,對(duì)象是不完整的,可能會(huì)出現(xiàn)未定義的行為。
7、最好將基類的析構(gòu)函數(shù)聲明為虛函數(shù)。(析構(gòu)函數(shù)比較特殊,因?yàn)榕缮惖奈鰳?gòu)函數(shù)跟基類的析構(gòu)函數(shù)名稱不一樣,但是構(gòu)成覆蓋,這里編譯器做了特殊處理)
8、虛表是所有類對(duì)象實(shí)例共用的。
當(dāng)前文章:學(xué)習(xí)C++中的多態(tài)
路徑分享:http://weahome.cn/article/pgjooj.html