C++之纯虚函数和抽象类
純虛函數和抽象類
1.基本概念
2.案例
#include <iostream> using namespace std;////面向抽象類編程(面向一套預先定義好的接口編程)//解耦合 ....模塊的劃分class Figure //抽象類 { public://閱讀一個統一的界面(接口),讓子類使用,讓子類必須去實現virtual void getArea() = 0 ; //純虛函數 protected: private: };class Circle : public Figure { public:Circle(int a, int b){this->a = a;this->b = b;}virtual void getArea(){cout<<"圓形的面積: "<<3.14*a*a<<endl;;}private:int a;int b; };class Tri : public Figure { public:Tri(int a, int b){this->a = a;this->b = b;}virtual void getArea() {cout<<"三角形的面積: "<<a*b/2<<endl;;}private:int a;int b; };class Square : public Figure { public:Square(int a, int b){this->a = a;this->b = b;}virtual void getArea() {cout<<"四邊形的面積: "<<a*b<<endl;;}private:int a;int b; };void objplay(Figure *base) {base->getArea(); //會發生多態 }void main511() {//Figure f; //抽象類不能被實例化Figure *base = NULL; //抽象類不能被實例化Circle c1(10, 20);Tri t1(20, 30);Square s1(50, 60);//面向抽象類編程(面向一套預先定義好的接口編程)objplay(&c1);objplay(&t1);objplay(&s1);//c1.getArea();cout<<"hello..."<<endl;system("pause");return ; }3.抽象類在多繼承中的應用
C++中沒有Java中的接口概念,抽象類可以模擬Java中的接口類。(接口和協議)
工程上的多繼承
- 被實際開發經驗拋棄的多繼承
- 工程開發中真正意義上的多繼承是幾乎不被使用的
- 多重繼承帶來的代碼復雜性遠多于其帶來的便利
- 多重繼承對代碼維護性上的影響是災難性的
- 在設計方法上,任何多繼承都可以用單繼承代替
多繼承中的二義性和多繼承不能解決的問題
C++沒有接口只有多繼承和抽象類
- 絕大多數面向對象語言都不支持多繼承
- 絕大多數面向對象語言都支持接口的概念
- C++中沒有接口的概念
- C++中可以使用純虛函數實現接口
- 接口類中只有函數原型定(純虛函數)義,沒有任何數據的定義。
實際工程經驗證明
- 多重繼承接口不會帶來二義性和復雜性等問題
- 多重繼承可以通過精心設計用單繼承和接口來代替
- 接口類只是一個功能說明,而不是功能實現。
- 子類需要根據功能說明定義功能實現。
多繼承的二義性
- 抽象類和多繼承更配哦
4.面向抽象類編程
- 計算程序猿工資
5.socket庫c++模型設計和實現
企業信息系統框架集成第三方產品
- 案例背景:一般的企業信息系統都有成熟的框架。軟件框架一般不發生變化,能自由的集成第三方廠商的產品。
- 案例需求:請你在企業信息系統框架中集成第三方廠商的Socket通信產品和第三方廠商加密產品。
- 第三方廠商的Socket通信產品:完成兩點之間的通信
- 第三方廠商加密產品:完成數據發送時加密;數據解密時解密。
案例要求:
1)能支持多個廠商的Socket通信產品入圍
2)能支持多個第三方廠商加密產品的入圍
3)企業信息系統框架不輕易發生框架
需求實現
- 思考1:企業信息系統框架、第三方產品如何分層
- 思考2:企業信息系統框架,如何自由集成第三方產品
(軟件設計:模塊要求松、接口要求緊) - 思考3:軟件分成以后,開發企業信息系統框架的程序員,應該做什么?第三方產品入圍應該做什么?
編碼實現
分析有多少個類 CSocketProtocol CSckFactoryImp1 CSckFactoryImp2
CEncDesProtocol HwEncdes ciscoEncdes
1、 定義 CSocketProtocol 抽象類
2、 編寫框架函數
3、 編寫框架測試函數
4、 廠商1(CSckFactoryImp1)實現CSocketProtocol、廠商2(CSckFactoryImp1)實現CSocketProtoco
5、 抽象加密接口(CEncDesProtocol)、加密廠商1(CHwImp)、加密廠商2(CCiscoImp)),集成實現業務模型
6、 框架(c語言函數方式,框架函數;c++類方式,框架類)
幾個重要的面向對象思想
* 繼承-組合(強弱)
* 注入
* 控制反轉 IOC
* MVC
* 面向對象思想擴展aop思想:aop思想是對繼承編程思想的有力的補充
實現步驟
2.廠商一的功能實現
- 類的頭文件
- 類的實現文件
3.廠商二的功能實現
- 類的頭文件
- 類的實現文件
4.測試socket功能文件
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std;#include "CSocketProtocol.h" #include "CSckFactoryImp1.h" #include "CSckFactoryImp2.h"//面向抽象類編程,框架實現完畢 int SckSendAndRec01(CSocketProtocol *sp, unsigned char *in, int inlen, unsigned char *out, int *outlen) {int ret = 0;ret = sp->cltSocketInit();if (ret != 0){goto End;}ret = sp->cltSocketSend(in, inlen);if (ret != 0){goto End;}ret = sp->cltSocketRev(out, outlen);if (ret != 0){goto End;}End:ret = sp->cltSocketDestory();return 0; }//寫一個框架 int main011() {int ret = 0;unsigned char in[4096];int inlen;unsigned char out[4096];int outlen = 0;strcpy((char *)in, "aadddddddddddaaaaaaaaaaa");inlen = 9;CSocketProtocol *sp = NULL;//sp = new CSckFactoryImp1sp = new CSckFactoryImp2; //ret = SckSendAndRec01(sp, in, inlen, out, &outlen);if (ret != 0){printf("func SckSendAndRec() err:%d \n", ret);return ret;}delete sp; //想通過父類指針 釋放所有的子類對象的資源 ..cout<<"hello..."<<endl;system("pause");return ret; }5.加密協議抽象類的定義
#pragma onceclass CEncDesProtocol { public:CEncDesProtocol(){}virtual ~CEncDesProtocol(){}virtual int EncData(unsigned char *plain, int plainlen, unsigned char *cryptdata, int *cryptlen) = 0;virtual int DecData(unsigned char *cryptdata, int cryptlen, unsigned char *plain, int *plainlen) = 0;};6.廠商一的加密功能實現
- 類的頭文件
- 類的實現文件
7.加密功能的測試文件
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std;#include "CSocketProtocol.h" #include "CSckFactoryImp1.h" #include "CSckFactoryImp2.h"#include "CEncDesProtocol.h" #include "HwEncDec.h"//面向抽象類編程,框架實現完畢 int SckSendAndRec(CSocketProtocol *sp, unsigned char *in, int inlen, unsigned char *out, int *outlen) {int ret = 0;ret = sp->cltSocketInit();if (ret != 0){goto End;}ret = sp->cltSocketSend(in, inlen);if (ret != 0){goto End;}ret = sp->cltSocketRev(out, outlen);if (ret != 0){goto End;}End:ret = sp->cltSocketDestory();return 0; }//面向抽象類編程,框架實現完畢 //c函數 int SckSendAndRec_EncDec(CSocketProtocol *sp, CEncDesProtocol *ed, unsigned char *in, int inlen, unsigned char *out, int *outlen) {int ret = 0;unsigned char data[4096];int datalen = 0;ret = sp->cltSocketInit();if (ret != 0){goto End;}ret = ed->EncData(in,inlen, data, &datalen);if (ret != 0){goto End;}ret = sp->cltSocketSend(data, datalen); //發送數據之前對數據加密 ..if (ret != 0){goto End;}ret = sp->cltSocketRev(data, &datalen); //收到的數據是密文,需要進行解密if (ret != 0){goto End;}ret = ed->DecData(data, datalen, out, outlen );if (ret != 0){goto End;}End:ret = sp->cltSocketDestory();return 0; }//寫一個框架 int main022() {int ret = 0;unsigned char in[4096];int inlen;unsigned char out[4096];int outlen = 0;strcpy((char *)in, "aadddddddddddaaaaaaaaaaa");inlen = 9;CSocketProtocol *sp = NULL;CEncDesProtocol *ed = NULL;//sp = new CSckFactoryImp1sp = new CSckFactoryImp2; //ed = new HwEncDec;ret = SckSendAndRec_EncDec(sp, ed, in, inlen, out, &outlen);if (ret != 0){printf("func SckSendAndRec() err:%d \n", ret);return ret;}delete sp; //想通過父類指針 釋放所有的子類對象的資源 ..cout<<"hello..."<<endl;system("pause");return ret; }加解密的代碼是des.h和des.c,可在前面“08文件操作”查看源代碼。
8.將測試框架從函數形式升級為類的形式
#define _CRT_SECURE_NO_WARNINGS #include <iostream> using namespace std;#include "CSocketProtocol.h" #include "CSckFactoryImp1.h" #include "CSckFactoryImp2.h"#include "CEncDesProtocol.h" #include "HwEncDec.h"//抽象類在多繼承中的應用 /* class MainOp : public CSocketProtocol, public CEncDesProtocol { public: protected: private:}; */class MainOp { public:MainOp(){this->sp = NULL;this->ed = NULL;}MainOp(CSocketProtocol *sp, CEncDesProtocol *ed){this->sp = sp;this->ed = ed;}//void setSp(CSocketProtocol *sp){this->sp = sp;}void setEd(CEncDesProtocol *ed){this->ed = ed;}public://面向抽象類編程,框架實現完畢int SckSendAndRec_EncDec3(CSocketProtocol *sp, CEncDesProtocol *ed, unsigned char *in, int inlen, unsigned char *out, int *outlen){int ret = 0;unsigned char data[4096];int datalen = 0;ret = sp->cltSocketInit();if (ret != 0){goto End;}ret = ed->EncData(in,inlen, data, &datalen);if (ret != 0){goto End;}ret = sp->cltSocketSend(data, datalen); //發送數據之前對數據加密 ..if (ret != 0){goto End;}ret = sp->cltSocketRev(data, &datalen); //收到的數據是密文,需要進行解密if (ret != 0){goto End;}ret = ed->DecData(data, datalen, out, outlen );if (ret != 0){goto End;}End:ret = sp->cltSocketDestory();return 0;}int SckSendAndRec_EncDec3(unsigned char *in, int inlen, unsigned char *out, int *outlen){int ret = 0;unsigned char data[4096];int datalen = 0;ret = this->sp->cltSocketInit();if (ret != 0){goto End;}ret = this->ed->EncData(in,inlen, data, &datalen);if (ret != 0){goto End;}ret = this->sp->cltSocketSend(data, datalen); //發送數據之前對數據加密 ..if (ret != 0){goto End;}ret = sp->cltSocketRev(data, &datalen); //收到的數據是密文,需要進行解密if (ret != 0){goto End;}ret = ed->DecData(data, datalen, out, outlen );if (ret != 0){goto End;}End:ret = sp->cltSocketDestory();return 0;}private:CSocketProtocol *sp;CEncDesProtocol *ed;};//寫一個框架 int main() {int ret = 0;unsigned char in[4096];int inlen;unsigned char out[4096];int outlen = 0;strcpy((char *)in, "aadddddddddddaaaaaaaaaaa");inlen = 9;MainOp *myMainOp = new MainOp;CSocketProtocol *sp = NULL;CEncDesProtocol *ed = NULL;//sp = new CSckFactoryImp1sp = new CSckFactoryImp2; //ed = new HwEncDec;myMainOp->setSp(sp);myMainOp->setEd(ed);ret = myMainOp->SckSendAndRec_EncDec3(in, inlen, out, &outlen);if (ret!= 0){printf("myMainOp SckSendAndRec_EncDec3() err\n ", ret);}delete sp;delete ed;delete myMainOp;cout<<"hello..."<<endl;system("pause");return ret; }無非就是將之前的全局函數封裝在一個測試用的類里面,然后該測試類擁有socket和加解密協議的基類對象作為該測試類的成員變量。
6.C語言回調函數和函數指針
結論:回調函數的本質:提前做了一個協議的約定(把函數的參數、函數返回值提前約定)
動態庫升級為框架的編碼實現
1、 動態庫中定義協議,并完成任務的調用
2、 加密廠商完成協議函數的編寫
3、 對接調試。
4、 動態庫中可以緩存第三方函數的入口地址,也可以不緩存,兩種實現方式。
案例總結
回調函數:利用函數指針做函數參數,實現的一種調用機制,具體任務的實現者,可以不知道什么時候被調用。
回調機制原理:
- 當具體事件發生時,調用者通過函數指針調用具體函數
- 回調機制將調用者和被調函數分開,兩者互不依賴
- 任務的實現 和 任務的調用 可以耦合 (提前進行接口的封裝和設計)
總結
以上是生活随笔為你收集整理的C++之纯虚函数和抽象类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么取消苹果手机自动续费_手机 App
- 下一篇: s3c2440移植MQTT