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

歡迎訪問 生活随笔!

生活随笔

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

c/c++

C++之纯虚函数和抽象类

發布時間:2023/12/19 c/c++ 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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++中可以使用純虛函數實現接口
    • 接口類中只有函數原型定(純虛函數)義,沒有任何數據的定義。
class Interface {public:virtual void func1() = 0;virtual void func2(int i) = 0;virtual void func3(int i) = 0; };
  • 實際工程經驗證明

    • 多重繼承接口不會帶來二義性和復雜性等問題
    • 多重繼承可以通過精心設計用單繼承和接口來代替
    • 接口類只是一個功能說明,而不是功能實現。
    • 子類需要根據功能說明定義功能實現。
  • 多繼承的二義性

#include <iostream> using namespace std;class B { public:int b; protected: private: };class B1 : virtual public B { public:int b1; protected: private: };class B2 : virtual public B { public:int b2; protected: private: };class C : public B1, public B2 { public:int c; protected: private: };void main61() {C myc;myc.c = 10;myc.b = 100;//二義性 error C2385: 對“b”的訪問不明確cout<<"hello..."<<endl;system("pause");return ; }
  • 抽象類和多繼承更配哦
#include <iostream> using namespace std;class Interface1 { public:virtual int add(int a, int b) = 0;virtual void print() = 0; };class Interface2 { public:virtual int mult(int a, int b) = 0;virtual void print() = 0; };class Parent { public:int getA(){a = 0;return a;} protected: private:int a; };class Child : public Parent, public Interface1, public Interface2 { public:virtual int add(int a, int b){cout<<"Child: add()已經執行\n";return a + b;}virtual void print(){cout<<"Child: print()已經執行\n";}virtual int mult(int a, int b){cout<<"Child: mult()已經執行\n";return a*b;} protected: private: };void main71() {Child c1;c1.print();Interface1 *it1 = &c1;it1->add(1, 2);Interface2 *it2 = &c1;it2->mult(3, 6);cout<<"hello..."<<endl;system("pause");return ; }

4.面向抽象類編程

  • 計算程序猿工資
#include <iostream> using namespace std;class programer{ public:virtual int getSal() = 0; };class junior_programer :public programer { private:char *name;char *obj;int sal; public:junior_programer(char *_name,char *_obj,int _sal){name = _name;obj = _obj;sal = _sal;}virtual int getSal(){cout << name << " " << obj << ": " << sal << endl;return sal;} protected: };class mid_programer :public programer { private:char *name;char *obj;int sal; public:mid_programer(char *_name, char *_obj, int _sal){name = _name;obj = _obj;sal = _sal;}virtual int getSal(){cout << name << " " << obj << ": " << sal << endl;return sal;} protected: };class adv_programer :public programer { private:char *name;char *obj;int sal; public:adv_programer(char *_name, char *_obj, int _sal){name = _name;obj = _obj;sal = _sal;}virtual int getSal(){cout << name << " " << obj << ": " << sal << endl;return sal;} protected: };class arch_programer :public programer { private:char *name;char *obj;int sal; public:arch_programer(char *_name, char *_obj, int _sal){name = _name;obj = _obj;sal = _sal;}virtual int getSal(){cout << name << " " << obj << ": " << sal << endl;return sal;} protected: };void CalProgSal(programer *base) {base->getSal(); }int main(void) {junior_programer jp("小王", "初級", 4000);mid_programer mp("小張", "中級", 8600);adv_programer ap("小李", "高級", 15000);//系統擴展arch_programer ar("高水平學員", "架構師", 24000);CalProgSal(&jp);CalProgSal(&mp);CalProgSal(&ap);CalProgSal(&ar);cout<<"Hello!"<<endl;system("pause");return 0; }

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思想是對繼承編程思想的有力的補充

實現步驟

  • 定義socket的抽象類和純虛函數
  • #pragma once#include <iostream> using namespace std;class CSocketProtocol { public:CSocketProtocol(){;}virtual ~CSocketProtocol() //虛析構函數的細節{;}//客戶端初始化 獲取handle上下virtual int cltSocketInit( /*out*/) = 0; //客戶端發報文virtual int cltSocketSend( unsigned char *buf /*in*/, int buflen /*in*/) = 0; //客戶端收報文virtual int cltSocketRev( unsigned char *buf /*in*/, int *buflen /*in out*/) = 0;//客戶端釋放資源virtual int cltSocketDestory() = 0;};

    2.廠商一的功能實現

    • 類的頭文件
    #pragma once#include <iostream> using namespace std; #include "CSocketProtocol.h"class CSckFactoryImp1 : public CSocketProtocol { public://客戶端初始化 獲取handle上下virtual int cltSocketInit( /*out*/); //客戶端發報文virtual int cltSocketSend( unsigned char *buf /*in*/, int buflen /*in*/); //客戶端收報文virtual int cltSocketRev( unsigned char *buf /*in*/, int *buflen /*in out*/);//客戶端釋放資源virtual int cltSocketDestory();private:unsigned char *p;int len ; };
    • 類的實現文件
    #include <iostream> using namespace std;#include "CSckFactoryImp1.h"//客戶端初始化 獲取handle上下int CSckFactoryImp1::cltSocketInit( /*out*/){p = NULL;len = 0 ;return 0;}//客戶端發報文int CSckFactoryImp1::cltSocketSend( unsigned char *buf /*in*/, int buflen /*in*/){p = (unsigned char * ) malloc(sizeof(unsigned char) * buflen);if (p == NULL){return -1;}memcpy(p, buf, buflen);len = buflen;return 0;}//客戶端收報文int CSckFactoryImp1::cltSocketRev( unsigned char *buf /*in*/, int *buflen /*in out*/){if (buf==NULL || buflen==NULL){return -1;}*buflen = this->len ;memcpy(buf, this->p, this->len);return 0;}//客戶端釋放資源int CSckFactoryImp1::cltSocketDestory(){if (p != NULL){free(p);p = NULL;len = 0;}return 0;}

    3.廠商二的功能實現

    • 類的頭文件
    #pragma once#include <iostream> using namespace std; #include "CSocketProtocol.h"class CSckFactoryImp2 : public CSocketProtocol { public://客戶端初始化 獲取handle上下virtual int cltSocketInit( /*out*/); //客戶端發報文virtual int cltSocketSend( unsigned char *buf /*in*/, int buflen /*in*/); //客戶端收報文virtual int cltSocketRev( unsigned char *buf /*in*/, int *buflen /*in out*/);//客戶端釋放資源virtual int cltSocketDestory();private:unsigned char *p;int len ; };
    • 類的實現文件
    #include <iostream> using namespace std;#include "CSckFactoryImp2.h"//客戶端初始化 獲取handle上下 int CSckFactoryImp2::cltSocketInit( /*out*/) {p = NULL;len = 0 ;return 0; }//客戶端發報文 int CSckFactoryImp2::cltSocketSend( unsigned char *buf /*in*/, int buflen /*in*/) {p = (unsigned char * ) malloc(sizeof(unsigned char) * buflen);if (p == NULL){return -1;}memcpy(p, buf, buflen);len = buflen;return 0; }//客戶端收報文 int CSckFactoryImp2::cltSocketRev( unsigned char *buf /*in*/, int *buflen /*in out*/) {if (buf==NULL || buflen==NULL){return -1;}*buflen = this->len ;memcpy(buf, this->p, this->len);return 0; }//客戶端釋放資源 int CSckFactoryImp2::cltSocketDestory() {if (p != NULL){free(p);p = NULL;len = 0;}return 0; }

    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.廠商一的加密功能實現

    • 類的頭文件
    #include <iostream> using namespace std;#include "CEncDesProtocol.h"class HwEncDec : public CEncDesProtocol { public:virtual int EncData(unsigned char *plain, int plainlen, unsigned char *cryptdata, int *cryptlen);virtual int DecData(unsigned char *cryptdata, int cryptlen, unsigned char *plain, int *plainlen); };
    • 類的實現文件
    #include <iostream> using namespace std; #include "HwEncDec.h" #include "des.h"int HwEncDec::EncData(unsigned char *plain, int plainlen, unsigned char *cryptdata, int *cryptlen) {int ret = 0;//用戶使用的函數ret = DesEnc(plain,plainlen, cryptdata, cryptlen);if (ret != 0){printf("func DesEnc() err:%d \n ", ret);return ret;}return ret; }int HwEncDec::DecData(unsigned char *cryptdata, int cryptlen, unsigned char *plain, int *plainlen) {int ret = 0;//用戶使用函數des解密ret = DesDec(cryptdata, cryptlen, plain, plainlen);if (ret != 0){printf("func DesDec() err:%d \n ", ret);return ret;}return ret; }

    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、 動態庫中定義協議,并完成任務的調用

    typedef int (*EncData)(unsigned char *inData,int inDataLen,unsigned char *outData,int *outDataLen,void *Ref, int RefLen); typedef int (*DecData)(unsigned char *inData,int inDataLen,unsigned char *outData,int *outDataLen,void *Ref, int RefLen);

    2、 加密廠商完成協議函數的編寫
    3、 對接調試。
    4、 動態庫中可以緩存第三方函數的入口地址,也可以不緩存,兩種實現方式。

    案例總結

    • 回調函數:利用函數指針做函數參數,實現的一種調用機制,具體任務的實現者,可以不知道什么時候被調用。

    • 回調機制原理:

      • 當具體事件發生時,調用者通過函數指針調用具體函數
      • 回調機制將調用者和被調函數分開,兩者互不依賴
      • 任務的實現 和 任務的調用 可以耦合 (提前進行接口的封裝和設計)

    總結

    以上是生活随笔為你收集整理的C++之纯虚函数和抽象类的全部內容,希望文章能夠幫你解決所遇到的問題。

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