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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

静态联编,动态联编,类指针之间的关系,虚函数与多态性,纯虚函数,虚析构函数

發(fā)布時間:2024/9/27 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 静态联编,动态联编,类指针之间的关系,虚函数与多态性,纯虚函数,虚析构函数 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1.靜態(tài)聯(lián)編,是程序的匹配,連接在編譯階段實現(xiàn),也稱為早期匹配。重載函數(shù)使用靜態(tài)聯(lián)編。

2.動態(tài)聯(lián)編是指程序聯(lián)編推遲到運行時進(jìn)行,所以又稱為晚期聯(lián)編。switch語句和if語句是動態(tài)聯(lián)編的例子。

#include<iostream>void go(int num) { }void go(char *str) { }//class //::在一個類中 class A { public:void go(int num){ }void go(char *str){} };void main() {//auto p = go;在編譯的階段就能判斷好的,靜態(tài)聯(lián)編void(*p1)(char *str) = go;//指針函數(shù)void(*p2)(int num) = go; //在編譯的時候就確定了的叫靜態(tài)聯(lián)編std::cin.get(); }//動態(tài)聯(lián)編 void main1() {int num;std::cin >> num;if (num > 10){system("calc");}else {system("notepad");} }

3.靜態(tài)聯(lián)編

?? 普通成員函數(shù)重載可表達(dá)為兩種形式

?? 在一個類說明中重載

?? 基類的成員函數(shù)在派生類重載。有3中編譯區(qū)分方法:

?? 1):根據(jù)參數(shù)的特征加以區(qū)分

???2):使用”::”加以區(qū)分

??????????例如:A::Show();

??????????有別于B::show()

??? (3):根據(jù)類對象加以區(qū)分

????????例如:Aobj.show();? 調(diào)用? A::Show();

?????????????????????????????? Bobj.show();? 調(diào)用? B::Show();

案例:


#include <iostream> //父類與之類之間的重載,同名函數(shù)會覆蓋 //即使參數(shù)類型不一樣,不能直接調(diào)用,必須調(diào)用父類默認(rèn)生成的對象來調(diào)用 class A { public:void go(){std::cout << "A---go";}void go(int num){std::cout << "A---go" << num;}void go(char *str){std::cout << "A---go" << str << "str";}void goA(char *str){std::cout << "A---go" << str << "str";} };class B :public A { public://const 函數(shù)重載一般適用于常量對象//非const一般適用于變量對象void go(){std::cout << "B---go";}void go() const{std::cout << "B---go const";} };void main2() {B *pb = new B;//pb->go(NULL);pb->goA("1");//當(dāng)父類和子類中出現(xiàn)了重名的函數(shù)的時候,即使參數(shù)類型不一樣,//不能直接調(diào)用,必須調(diào)用父類默認(rèn)生成的對象來調(diào)用。//pb->go("1"); //C語言中的NULL可以打印,但是C++中的空指針式不可以打印的pb->A::go(NULL); //當(dāng)調(diào)用pb->A::go("123");//pb->A::go(nullptr);//C++空指針不能打印std::cin.get();//運行結(jié)果是:A---go1strA---go0A---go123str }void main() {B *p = new B;p->go();const B *pb = new B;pb->go();std::cin.get(); }

4.類指針的關(guān)系

???基類指針和派生類指針與基類對象和派生類對象4種可能匹配。

????? A:直接用基類指針引用基類對象。

????? B:直接用派生類指針引用派生類對象。

????? C:用基類指針引用一個派生類對象。

????? D:用派生類指針引用一個基類對象。


5.類與指針之間的關(guān)系

??????Adynamic適用于虛函數(shù)

????? B類而言,數(shù)據(jù)是私有,代碼是公有的

????? C指針為空,指向一個類,可以直接調(diào)用方法

????? D涉及內(nèi)部成員會崩潰,不涉及可以執(zhí)行

????? E父類指針引用父類對象,完全正常引用

????? F子類指針引用子類對象,覆蓋父類的同名函數(shù)

????? G父類指針引用子類對象,只能引用父類中的函數(shù)

????? H子類指針,引用父類對象,子類不涉及內(nèi)部數(shù)據(jù)的函數(shù)會調(diào)用成功

????? I涉及到內(nèi)部數(shù)據(jù)的會調(diào)用成功,執(zhí)行失敗

???? J子類指針可以引用父類的不重名的函數(shù)

???? K子類指針(不是pzi->fu::print();方法)無法引用父類的同名方法

案例如下:

fu.h

#pragma once #include <iostream>class fu { public:fu();~fu();char * strfu;void print();void fufu(); }; zi.h #pragma once #include "fu.h" class zi :public fu { public:zi();~zi();char *strzi;char ch[900000000];void print();void zizi(); }; fu.cpp #include "fu.h"fu::fu() {this->strfu = "父親";std::cout << "fu create" << std::endl; }fu::~fu() {std::cout << "fu delete" << std::endl; }void fu::print() {std::cout << this->strfu << "\n"; }void fu::fufu() {std::cout << "我是你爹" << "\n"; } zi.cpp #include "fu.h"fu::fu() {this->strfu = "父親";std::cout << "fu create" << std::endl; }fu::~fu() {std::cout << "fu delete" << std::endl; }void fu::print() {std::cout << this->strfu << "\n"; }void fu::fufu() {std::cout << "我是你爹" << "\n"; } main.cpp #include <iostream>#include"fu.h" #include "zi.h"//dynamic適用于虛函數(shù)//類而言,數(shù)據(jù)是私有,代碼是公有的 //指針為空,指向一個類,可以直接調(diào)用方法 //涉及內(nèi)部成員會崩潰,不涉及可以執(zhí)行//父類指針引用父類對象,完全正常引用 //子類指針引用子類對象,覆蓋父類的同名函數(shù) //父類指針引用子類對象,只能引用父類中的函數(shù) //子類指針,引用父類對象,子類不涉及內(nèi)部數(shù)據(jù)的函數(shù)會調(diào)用成功 //涉及到內(nèi)部數(shù)據(jù)的會調(diào)用成功,執(zhí)行失敗 //子類指針可以引用父類的不重名的函數(shù) //子類指針(不是pzi->fu::print();方法)無法引用父類 //的同名方法 void main1() {{//fu *pfu = new fu;//delete pfu;}{//前后一致的不會出現(xiàn)問題zi *pzi = new zi;delete pzi;}{//fu *pfu = new zi;//內(nèi)存泄漏,理解:后面的空間大,前面的空間小,釋放前面,出現(xiàn)內(nèi)存泄露//delete pfu;}{//fu *pfu = new fu;zi *pzi = static_cast<zi *>(new fu);delete pzi;//內(nèi)存越界,超過界限釋放內(nèi)存,有時出錯,有時無錯}std::cin.get(); }void main2() {zi *pzi(nullptr);//會調(diào)用自己的函數(shù)pzi->zizi();//結(jié)果是:我是你兒子std::cin.get(); }void main() {fu *pfu = new fu;zi *pzi = static_cast<zi *>(pfu);pzi->fufu();//我是你爹pzi->zizi();//我是你兒子pzi->fu::print();//父親//pzi->print();//std::cout << pzi->strzi << std::endl;//pzi->print();std::cin.get(); }

6.冠以關(guān)鍵字virtual的成員函數(shù)稱為虛函數(shù)。

實現(xiàn)運行時多態(tài)的關(guān)鍵首先是要說明虛函數(shù),另外,必須用基類指針調(diào)用派生類的不同實現(xiàn)版本。

7.??對于虛函數(shù)的總結(jié):

?? A對于繼承的情況,如果自來實現(xiàn)了父類的同名函數(shù),

?? B當(dāng)指針調(diào)用的時候會一直調(diào)用父類的函數(shù),當(dāng)成員函數(shù)加了virtual

?? C關(guān)鍵字修飾之后,子類才會調(diào)用自己的函數(shù)。

案例:

#include<iostream>//總結(jié):對于繼承的情況,如果實現(xiàn)了父類的同名函數(shù) //當(dāng)指針調(diào)用的時候會一直調(diào)用父類的函數(shù),當(dāng)成員函數(shù)加了virtual關(guān)鍵字后,子類才會調(diào)用自己的函數(shù)。 class fu { public:virtual void name() //虛函數(shù)有4個字節(jié),32位的,實際上是一個函數(shù)指針,自動調(diào)用子類的函數(shù)覆蓋虛函數(shù){std::cout << "父類";std::cout << "x=" << x << "\n";}int x;fu(int a) :x(a){} };class zi :public fu { public:void name(){std::cout << "子類";std::cout << "x=" << x << ",y=" << y << "\n";}int y;zi(int a, int b) :fu(a), y(b){} };class sun :public zi { public:void name(){std::cout << "孫類";std::cout << "x=" << x << ",y=" << y << ",z=" << z << "\n";}int z;sun(int a, int b, int c) :zi(a, b), z(c){} };int main(int argc, char *argv[]) {//下面的結(jié)果為8,說明虛函數(shù)的大小為4字節(jié)std::cout << sizeof(fu) << std::endl;fu fu1(1);zi zi1(2, 3);sun sun1(4, 5, 6);fu *pfu;pfu = &fu1;pfu->name();//打印出:父類x=1pfu = &zi1;pfu->name();//父類加了virtual之后,此處打印出:子類x=2,y=3pfu = &sun1;pfu->name();//父類加了virtual之后,此處打印出:孫類x=4,y=5std::cin.get(); }

8:純虛函數(shù)


#include <iostream>using namespace std;//因為base其中有純虛函數(shù),所以不能實例化了。 class base { public:int num;void goA(){}//下面是一個純虛函數(shù)virtual void show()=0; //帶了純虛函數(shù)就是抽象類//可以有實現(xiàn),也可以沒有實現(xiàn),可以放在內(nèi)部外部 };class run:public base { public:void show(){std::cout << "run show();" << std::endl;} };int main() {cout << "Hello World!" << endl;//base base1;抽象類無法實例化run runInstance;runInstance.show();return 0; } 運行結(jié)果:

案例2


#include<iostream>class base { public://純虛函數(shù),有無定義都可以//有一個純虛函數(shù),都是抽象類,無法實例化virtual void run() = 0 //限定一個類不能實例化,作為專門的接口,QT里面不可以在內(nèi)部定義。{std::cout << "base run\n";}virtual ~base(){} };//抽象類不可以用于函數(shù)的參數(shù)以及返回值類型 //抽象類指針是可以 base * test(base *p) {base *pbase(nullptr);return pbase; }class boy :public base { public:void run(){std::cout << "男孩奔跑\n";} };class girl :public base { public:void run(){std::cout << "女孩奔跑\n";} };void main() {//抽象類無法實例化對象,可以實話指針//純虛函數(shù)與抽象類與虛函數(shù)起到接口的作用//用同一個接口完成不同的功能//純虛函數(shù)完全就是為了接口的存在,有了純虛函數(shù)的類無法實例化//虛函數(shù)占4個字節(jié),就是指針,函數(shù)指針boy boy1;girl girl1;base *p(nullptr);p = &boy1;p->run();p = &girl1;p->run();std::cin.get(); }

9.虛析構(gòu)函數(shù),在析構(gòu)函數(shù)的前面加上virtual

案例代碼如下:

#include <iostream>using namespace std;class A { public://構(gòu)造函數(shù)不可以是虛函數(shù),如果是了就不可以再構(gòu)造,//沒有辦法創(chuàng)建子類中的父類對象A(){std::cout << "a create" << std::endl;}//虛析構(gòu)函數(shù),讓父類指針正確的釋放子類對象的內(nèi)存virtual ~A(){std::cout << "a delete" << std::endl;} };class B:public A { public:B()//B創(chuàng)建自動調(diào)用A的構(gòu)造函數(shù){std::cout << "b create" << std::endl;}~B()//B析構(gòu)的時候會自動調(diào)用A的析構(gòu)函數(shù){std::cout << "b delete" << std::endl;} };int main() {A *p = new B;delete p;return 0; }

如果析構(gòu)函數(shù)前沒有加virtual,運行結(jié)果如下:


如果析構(gòu)函數(shù)前加了virtual,運行結(jié)果如下:


10. 者多個虛函數(shù),或者多個純虛函數(shù)都占四個字節(jié)

案例如下:


#include <iostream>using namespace std;//抽象類也可以實現(xiàn)繼承 //僅有一個指針指向虛函數(shù)表//1個或者多個虛函數(shù),或者多個純虛函數(shù)都占四個字節(jié) //一個指針存儲了虛函數(shù)標(biāo)的地址class basebase { public:virtual void show() = 0;virtual void hide() = 0;virtual void run() = 0; };class base { public:virtual void show(){}virtual void hide(){}virtual void run(){} };int main() {cout << sizeof(basebase) << endl;//結(jié)果是4cout << sizeof(base) << endl;//結(jié)果為4return 0; }

11.子類只有都實現(xiàn)了基類中的純虛函數(shù)之后才可以實例化

案例說明如下:

#include "mainwindow.h" #include <QApplication> #include<QPushButton> #include<QLabel> #include<iostream>//抽象類也可以實現(xiàn)繼承 class basebase { public:virtual void show()=0;virtual void hide()=0; };//接口,操作不同的類對象的方法 class base :public basebase { public:virtual void resize(int x,int y)=0;virtual void move (int cx,int cy)=0; };class myself: public base { public://只要有一個接口的沒有實現(xiàn),抽象類//把所有就接口都實現(xiàn)了的類才可以實例化void show(){}void hide(){} };class mydialog: public base { public:MainWindow w;void show(){w.show();}void hide(){w.hide();}void resize(int x,int y){w.resize(x,y);}void move (int cx,int cy){w.move(cx,cy);} };class mybutton: public base { public:QPushButton w;void show(){w.show();}void hide(){w.hide();}void resize(int x,int y){w.resize(x,y);}void move (int cx,int cy){w.move(cx,cy);} };class mylabel: public base { public:QLabel w;void show(){w.show();}void hide(){w.hide();}void resize(int x,int y){w.resize(x,y);}void move (int cx,int cy){w.move(cx,cy);} };int main(int argc, char *argv[]) {QApplication a(argc, argv);//myself my1;return a.exec(); }int main1(int argc, char *argv[]) {QApplication a(argc, argv);mydialog dialog1;mybutton button1;mylabel label1;//只有在.pro中加上CONFIG += c++11后nullptr才可以使用,因為其是C++11特性base *pbase(nullptr);pbase =&dialog1;pbase->show();pbase->resize(100,200);pbase =&button1;pbase->show();pbase->resize(200,200);pbase=&label1;pbase->show();pbase->resize(300,200);return a.exec(); }





































總結(jié)

以上是生活随笔為你收集整理的静态联编,动态联编,类指针之间的关系,虚函数与多态性,纯虚函数,虚析构函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。