日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ 重载运算符 继承 多态 (超详细)

發布時間:2023/12/15 c/c++ 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ 重载运算符 继承 多态 (超详细) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

(一)重載運算符:

(1)聲明與定義格式
一般是類內聲明,類外定義,雖然可以在類內定義,但 寫前面堆一堆不好看!!!
類內聲明

class Demo {返回值類型 operator 運算符(形參表); }

類外定義:

返回類型 Demo(類名)::operator運算符(形參表) {函數體 }

(2)雙目運算符重載為成員函數
當重載運算符為雙目運算符時,形參表中只有一個參數作為右操作數。當前對象作為左操作數,通過this指針隱式傳遞給函數,一個例子來介紹。
實例:
寫到最后突然想起來,用int不能實現浮點數的全部特性0.03就不能實現,所以僅作為一個例子。

class Myfloat {int inter;int deci; public:Myfloat(int a,int b):inter(a),deci(b){}Myfloat operator+(Myfloat const &temp) const;Myfloat operator-(Myfloat const &temp) const; }; Myfloat Myfloat::operator+(Myfloat const &temp) const {return Myfloat(inter+temp.inter,deci+temp.deci); } Myfloat Myfloat::operator-(Myfloat const &temp) const {return Myfloat(inter-temp.inter,deci-temp.deci); }

現在只是重載了加減號,實現了自定義浮點數的運算,但是還不成熟,咱們一點一點來豐滿這個代碼,這個類。(3)單目運算符重載為成員函數
此時參數表中沒有參數,只有當前對象作為運算符的一個操作數。
實例:

#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> using namespace std; class Myfloat {int inter;int deci; public:Myfloat(int a,int b):inter(a),deci(b){}Myfloat operator+(Myfloat const &temp) const;Myfloat operator-(Myfloat const &temp) const;Myfloat operator--();Myfloat operator++();Myfloat operator--(int); //補充一個虛操作數,表示前置操作Myfloat operator++(int); }; Myfloat Myfloat::operator+(Myfloat const &temp) const {return Myfloat(inter+temp.inter,deci+temp.deci); } Myfloat Myfloat::operator-(Myfloat const &temp) const {return Myfloat(inter-temp.inter,deci-temp.deci); } Myfloat Myfloat::operator--() {return Myfloat(inter--,deci);} Myfloat Myfloat::operator++() {return Myfloat(inter++,deci);} Myfloat Myfloat::operator--(int) {return Myfloat(--inter,deci);}

要區分前置與后置運算要加一個(需操作數)告訴機器是前置還是后置。

(3) 友元函數重載+重載輸入輸出流(用的稀爛用的多比較重要)
在左右操作數類型不同時上述重載方式都不能正常使用,這時候就需要兩個操作數,在類外重載,因類外不能直接調用,所以要把該函數聲明為類的友元。

#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> using namespace std; class Myfloat {int inter;int deci; public:Myfloat(int a,int b):inter(a),deci(b){}Myfloat operator+(Myfloat const &temp) const;Myfloat operator-(Myfloat const &temp) const;Myfloat operator--();Myfloat operator++();Myfloat operator--(int); //補充一個虛操作數,表示前置操作Myfloat operator++(int);friend ostream& operator<<(ostream out,Myfloat &w) ;friend istream &operator>>(istream in,Myfloat &w); }; Myfloat Myfloat::operator+(Myfloat const &temp) const{return Myfloat(inter+temp.inter,deci+temp.deci);} Myfloat Myfloat::operator-(Myfloat const &temp) const{return Myfloat(inter-temp.inter,deci-temp.deci);} Myfloat Myfloat::operator--() {return Myfloat(inter--,deci);} Myfloat Myfloat::operator++() {return Myfloat(inter++,deci);} Myfloat Myfloat::operator--(int) {return Myfloat(--inter,deci);} Myfloat Myfloat::operator++(int) {return Myfloat(++inter,deci);} ostream& operator<<(ostream out,Myfloat &w) {out<<w.inter<<'.'<<w.deci; } istream &operator>>(istream in,Myfloat &w) {in>>w.inter>>w.deci; }

(4)賦值運算符重載用于對象數據的復制
用非類A類型的值為類A的對象賦值時(當然,這種情況下我們可以不提供相應的賦值運算符重載函數,而只提供相應的構造函數,如更有重載函數會優先調用重載后的賦值運算符)。
當用類A類型的值為類A的對象賦值,且類A的數據成員中含有指針的情況下,必須顯式提供賦值運算符重載函數。

#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<cmath> using namespace std; class Myfloat {int inter;int deci; public:Myfloat(int a,int b):inter(a),deci(b){}Myfloat operator+(Myfloat const &temp) const;Myfloat operator-(Myfloat const &temp) const;Myfloat operator--();Myfloat operator++();Myfloat operator--(int); //補充一個虛操作數,表示前置操作Myfloat operator++(int);friend ostream& operator<<(ostream out,Myfloat &w) ;friend istream &operator>>(istream in,Myfloat &w);Myfloat& operator=(const Myfloat &temp ) ;//寫或不寫都可以,這種如果按照默認的方式一一對應復制,可以不寫。Myfloat& operator=(const int &w ) ; }; Myfloat Myfloat::operator+(Myfloat const &temp) const{return Myfloat(inter+temp.inter,deci+temp.deci);} Myfloat Myfloat::operator-(Myfloat const &temp) const{return Myfloat(inter-temp.inter,deci-temp.deci);} Myfloat Myfloat::operator--() {return Myfloat(inter--,deci);} Myfloat Myfloat::operator++() {return Myfloat(inter++,deci);} Myfloat Myfloat::operator--(int) {return Myfloat(--inter,deci);} Myfloat Myfloat::operator++(int) {return Myfloat(++inter,deci);} ostream& operator<<(ostream out,Myfloat &w) {out<<w.inter<<'.'<<w.deci; } istream &operator>>(istream in,Myfloat &w) {in>>w.inter>>w.deci; } Myfloat& Myfloat::operator=(const Myfloat &temp) {inter=temp.inter;deci=temp.deci;return *this; } Myfloat& Myfloat::operator=(const int &w) {inter=w;return *this; }





(二)基類與派生類

(1)繼承語法形式

class 派生類名:基類名表{數據成員和成員函數聲明}

基類類名表構成: 訪問控制 基類名1 訪問控制 基類名2…
繼承多各類時叫做多繼承,容易產生二義性,一般不用。

訪問控制有三種
public:公有繼承
private:私有繼承
protected:保護繼承
實例

class People { }class Student:public People


(2)派生類的生成過程

  • 吸收基類成員:除構造和析構函數外
  • 改造基類成員:通過在派生類中定義同名成員屏蔽基類成員在派生類中直接調用,仍可以基類指針調用同名成員
  • .添加新成員
  • (3)派生類特點

  • 子類擁有父類除了父類構造和析構函數,所有的成員函數和成員變量;
  • 2.子類就是一種特殊的父類;
  • 子類對象可以當做父類的對象使用;
  • 子類可以擁有父類沒有的方法和屬性。
  • (4)派生類中的靜態數據成員
    基類中定義的靜態成員,將被所有派生類共享
    2、基類初始化:
    (5)派生類的初始化

    派生類構造函數聲明格式為:
    派生類構造函數(變元表):基類(變元表)、對象成員1(變元表)

    構造函數執行順序:基類——對象成員(類對象成員的初始化)——派生類
    //一開始不理解,現在理解了
    舉個栗子:

    class People { protected:string name;string xb; public:People(string a,string b):name(a),xb(b){} }; class Cloth {string color;int mysize; public:Cloth(string c,int m):color(c),mysize(m){} }; class Student:public People {string id;Cloth coat; public:Student(string id,string name,string xh,string color,int size) :People(name,xb),coat(color,size),id(id){} };

    執行順序跟我寫的順序一樣,但不是因為按這個順序寫的原因,就像成員變量初始化,也是按這定義順序初始化,與自己寫的初始化順序無關。
    構造函數的執行順序:基類→對象成員→派生類;
    (6)派生類構造函數和析構函數的使用原則

    基類的構造函數和析構函數不能繼承
    派生類是否定義析構函數與所屬基類無關
    如果基類沒有定義構造函數或是定義無參構造函數,派生類可以不定義構造函數。
    如果基類無無參構造函數,派生類必須定義構造函數
    如果派生類基類為連續基類繼承,每個派生類只負責直接基類的構造

    (7)派生類析構函數

    與構造函數執行順序相反,派生-----對象-----基類

    (8)賦值兼容原則
    這個規則可以簡述為能放基類的地方,放派生類一定可以使用,在程序中需要使用基類對象的地方都可以用公有派生類的對象代替。
    例:

    class Base{}; class Drived{}; Base demo1,Drived demo2; demo1=demo2; //派生類對象可以賦值給基類對象: Base&Bdemo3=demo2; //派生類對象可以初始化基類引用; Base *Bpo=&demo2;//派生類對象可以賦給指向基類對象的指針;//多態實現的方法

    主要是派生類中一定包含基類中所有成員,在使用中,一定可以找到對應成員。

    賦值兼容應注意的問題:

  • 指向基類的指針可以指向公有派生類的對象,但不允許指向它的私有派生類的對象。
  • 允許將一個聲明為指向基類的指針指向其公有派生類對象,但是不能將一個聲明為指向派生類對象的指針指向基類對象。
  • 聲明為指向基類對象的指針,當其指向公有派生類對象時,只能用它來直接訪問派生類中從基類繼承來的成員,而不能直接訪問公有派生類的定義的成員。
  • 可以理解為派生類完全包含基類,指向基類的任何成員,都可以在公有派生類中找到對應的成員對象與之對應,如果是私有繼承,能找到但是不能訪問。但是派生類中有的對象,基類中不一定會有,所以不能這么操作。







    (三)虛函數與多態:

    (1)多態的概念:
    一個接口,多種使用方法
    (2)封裝的作用:
    封裝可以是得代碼模塊化;繼承可以擴展已經存在的代碼,都是為了代代碼重用;
    **(3)多態的目的:**接口重用
    (4)靜態聯編和動態聯編分別表示什么?
    在編譯的時候能夠確定對象所調用的成員函數的地址則為靜態聯編,一般的調用方式;
    動態聯編:指的是在程序運行的時候動態地進行,根據當時的情況來確定調用哪個同名函數,父類指針指向哪個子類,就調用哪個子類的同名函數,實際上是在運行的時候虛函數的實現;

    #include<iostream> using namespace std;class Basic { public:void oper1(){printf("1\n");}virtual void oper2(){printf("2\n");} }; class Direved : public Basic { public:void oper1(){printf("3\n");}void oper2(){printf("4\n");} }; int main(void) {Basic a;Direved b;Basic *p = &a; // 定義一個基類指針 p->oper1(); //基類的oper1p->oper2(); //基類的oper2p = &b; //基類指針指向了派生類p->oper1(); //不是虛函數,仍時基類oper1p->oper2(); //是虛函數構成多態,是派生類的oper2return 0; }

    運行結果過如下,重點關注是否為虛函數時函數調用的區別。

    構成虛函數的必要條件:
    函數返回類型一樣,參數表一樣,函數名一樣,同時需要關鍵字vitrual,缺一不可。

    class Basic {vitrual void p(){ 函數體}; } class Direved :public Basic //構成虛函數的多態 {void p(){ 函數體}; } class Basic {void p(){ 函數體}; } class Direved :public Basic //不構成虛函數 {void p(){ 函數體}; } class Basic {vitrual void p(){ 函數體}; } class Direved :public Basic //不構成虛函數 {void p(int a){ 函數體}; } class Basic {vitrual void p(){ 函數體}; } class Direved :public Basic //不構成虛函數 {double p(){ 函數體}; }

    (5)C++純虛函數
    1.純虛函數是在基類中聲明的虛函數,它在基類中沒有定義,但要求任何派生類都要定義自己的實現方法。在基類中實現純虛函數的方法是在函數原型后加“=0”

    virtual void funtion()=0

    1、為了方便使用多態特性,我們常常需要在基類中定義虛擬函數。
    2、在很多情況下,基類本身生成對象是不合情理的。例如,動物作為一個基類可以派生出老虎、孔雀等子類,但動物本身生成對象明顯不合常理。

    Class animals {virtual void mingjiao()//動物基類,到底是什么動物呢,該怎么鳴叫?當無法合理的給予基類定義虛函數時,常用純虛函數。{} }

    為了解決上述問題,引入了純虛函數的概念

    Class animals {virtual void mingjiao()=0}

    則編譯器要求在派生類中必須予以重寫以實現多態性。同時含有純虛擬函數的類稱為抽象類,它不能生成對象。這樣就很好地解決了上述兩個問題。
    注意含有純虛函數的類,不能直接聲明對象!!!!!!!!

    (6)多態性 實現的兩種方式
    a、編譯時多態性:通過重載函數實現
    b、運行時多態性:通過虛函數實現。

    總結

    以上是生活随笔為你收集整理的C++ 重载运算符 继承 多态 (超详细)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。