静态联编,动态联编,类指针之间的关系,虚函数与多态性,纯虚函数,虚析构函数
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();
案例:
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ù)。
案例:
8:純虛函數(shù)
案例2:
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 "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)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 商业服务网点超过300平方可以开餐饮吗
- 下一篇: 异型链表