19纯虚函数和抽象类
来源:互联网 发布:双十一 淘宝 消费人群 编辑:程序博客网 时间:2024/06/01 08:50
纯虚函数和抽象类
- 纯虚函数和抽象类
- 基本概念
- 案例
- 抽象类在多继承中的应用
- 面向抽象类编程
- socket库c模型设计和实现
- 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 CSckFactoryImp1 sp = 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 CSckFactoryImp1 sp = 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 CSckFactoryImp1 sp = 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、 动态库中可以缓存第三方函数的入口地址,也可以不缓存,两种实现方式。
案例总结
回调函数:利用函数指针做函数参数,实现的一种调用机制,具体任务的实现者,可以不知道什么时候被调用。
回调机制原理:
- 当具体事件发生时,调用者通过函数指针调用具体函数
- 回调机制将调用者和被调函数分开,两者互不依赖
- 任务的实现 和 任务的调用 可以耦合 (提前进行接口的封装和设计)
- 19纯虚函数和抽象类
- 抽象类和纯虚函数
- 纯虚函数和抽象类
- 虚基类 、 纯虚函数和抽象类
- 纯虚函数和抽象类
- 纯虚函数和抽象类
- 纯虚函数和抽象类
- 抽象基类和纯虚函数
- 抽象类和纯虚函数
- 纯虚函数和抽象基类
- 纯虚函数和抽象类
- 纯虚函数和抽象类
- 【c++】纯虚函数和抽象类
- 纯虚函数和抽象类
- 抽象类和纯虚函数
- 纯虚函数和抽象基类
- 多态性:纯虚函数和抽象类
- 抽象基类和纯虚函数
- codeforces 2016-2017 TW Wrold Final Contest J. Zero Game
- 关于CSS的规范
- 【codevs1732】Fibonacci数列 2(矩阵快速幂)
- 【计算机网络】TCP协议详解
- Python中的函数(三)
- 19纯虚函数和抽象类
- Ubuntu下使用Pylon相机
- iOS 视频录制 包括预览图片与视频还有写入自己自定义的App相册 微信小视频
- R-CNN,SPP-NET, Fast-R-CNN,Faster-R-CNN, YOLO,系列深度学习检测方法
- 网络---端口
- python中Matplotlib库显示界面中进行鼠标交互绘制操作
- Gilde加载图片
- 多彩烟花
- P1996 约瑟夫问题