C++基础:纯虚函数、抽象类、编程案例
2021-05-06 10:29
标签:this Once 指针变量 名称 利用 子类 方式 自己的 base (1)纯虚函数 纯虚函数是一个在基类中说明的虚函数,在基类中没有定义,要求任何派生类都定义自己的版本; 纯虚函数位各派生类提供一个公共界面(接口的封装和设计、软件的模块功能划分); (2)抽象类 一个具有纯虚函数的基类成为抽象类 定义抽象类 Figure,纯虚函数 get_area 提供接口,由各个派生类自己实现函数的功能 C++中没有 Java 中的接口概念,抽象类可以模拟 Java 中的接口类。 多继承的应用场景:继承多个接口类(纯虚函数实现接口) C++中可以使用纯虚函数实现接口;接口类中只有函数原型定义,没有任何数据的定义。 多重继承接口不会带来二义性和复杂性等问题; 接口类只是一个功能说明,而不是功能实现。 编写一个程序,计算程序员( programmer )工资 (1)要求计算初级程序员(junior_programmer)中级程序员(mid_programmer)高级程序员(adv_programmer)的工资 (2)要求利用抽象类统一界面,方便程序的扩展 虚函数和多态性使成员函数根据调用对象的类型产生不同的动作 面向抽象类编程(面向接口编程)是项目开发中重要技能之一 几个重要的面向对象思想:继承-组合、注入、控制反转(IOC)、MVC、aop 需求: 在系统框架中集成 Socket通信产品 和 加解密产品 Socket 通信产品:完成两点之间的通信; 加密产品:完成数据发送时加密;数据解密时解密; 设计: 实现: SocketProtocol.h CEncDesProtocol.h SocketImp.h SocketImp.cpp EncDesImp.h EncDesImp.cpp Test_Socket.cpp 函数三要素:名称、参数、返回值 C语言中的函数有自己特定的类型 函数类型: 函数指针:函数指针用于指向一个函数,函数名是函数体的入口地址; (1)可以通过函数类型定义函数指针: (2)可以直接定义: (1)数组指针(数组类型 --> 数组指针类型 --> 数组指针变量) (2)函数指针(函数类型 --> 函数指针类型 --> 函数指针变量) 当函数指针操作函数的参数,传递给一个被调用函数,被调用函数就可以通过这个指针调用外部的函数,形成了回调 思路: (1)任务的实现,任务的操作框架,任务的调用有效的分离; (2)任务的框架不用改变,去调用不同的函数,实现不同的功能 --> 通过回调函数调用不同的函数; (3)回调函数:提前定义了一个协议(把函数参数、函数返回值提前约定),实现解耦合; 显示调用dll中的函数:通过 TestDll 动态库:抽象一个套接口,单独封装成模块,给别人调用,无法扩展; 框架:能自由扩展,自由的集成第三方的产品; 回调机制原理: 当具体事件发生时,调用者通过函数指针调用具体函数; 回调机制的将调用者和被调函数分开,两者互不依赖; C++基础:纯虚函数、抽象类、编程案例 标签:this Once 指针变量 名称 利用 子类 方式 自己的 base 原文地址:https://www.cnblogs.com/2dx3906/p/13189739.html纯虚函数和抽象类
基本概念
// 抽象类
class Base
{
public:
virtual void fun1() = 0; // 纯虚函数
virtual void fun2() = 0;
};
void main()
{
//Base b; // err,抽象类不能实例化
Base* p;
}
抽象类案例
// 抽象类 figure图形
class Figure
{
public:
// 纯虚函数
virtual void get_area() = 0; // 求面积
};
class Circle : public Figure
{
public:
Circle(int r, int b)
{
this->r = r;
this->b = b;
}
virtual void get_area()
{
cout h = h;
this->d = d;
}
virtual void get_area()
{
cout h = h;
this->d = d;
}
virtual void get_area()
{
cout get_area(); //多态
}
void main()
{
Figure* pF = NULL;
Circle c(10, 0);
Triangle t(20, 30);
Square s(40, 50);
// 通过父类指针指向子类对象
area(&c);
area(&t);
area(&s);
system("pause");
}
抽象类在多继承中的应用
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 test : public Interface1, public Interface2
{
public:
virtual void print()
{
cout add(1, 2);
Interface2 *it2 = &c1;
it2->mult(3, 4);
system("pause");
return;
}
抽象类知识点强化
// 抽象类 programmer
class programmer
{
public:
// 纯虚函数
virtual void get_salary() = 0;
};
//初级程序员
class junior_programmer : public programmer
{
public:
junior_programmer(char *name, char *job, int sal)
{
this->name = name;
this->job = job;
this->sal = sal;
}
virtual void get_salary()
{
cout name = name;
this->job = job;
this->sal = sal;
}
virtual void get_salary()
{
cout name = name;
this->job = job;
this->sal = sal;
}
virtual void get_salary()
{
cout get_salary();
}
void main()
{
// 初始化
junior_programmer jp("张三", "初级工程师", 3000);
mid_programmer mp("李四", "中级工程师", 8000);
adv_programmer ap("王五", "高级工程师", 10000);
CalProgSal(&jp);
CalProgSal(&mp);
CalProgSal(&ap);
system("pause");
return;
}
面向对象类编程思想
案例:socket库C++模型设计与实现
CSocketProtocol
:Socket接口类CSocketImp
:Socket产品类CEncDesProtocol
:des接口类CEncDesImp
:des产品类
int SckSendAndRec_EncDec()
class SocketAndEncDec
: 继承或组合
系统框架 ---> 接口层
#pragma once
//接口层
//Socket接口类
class CSocketProtocol
{
public:
CSocketProtocol(){;}
// 虚析构函数
virtual ~CSocketProtocol(){;}
//---------------第一套api接口-----Begin---------------//
//客户端初始化 获取handle上下
virtual int cltSocketInit(/*out*/) = 0;
//客户端发报文
virtual int cltSocketSend(/*in*/ unsigned char* buf /*in*/, int buflen /*in*/) = 0;
//客户端收报文
virtual int cltSocketRev(/*in*/ unsigned char* buf /*in*/, int* buflen /*out*/) = 0;
//客户端释放资源
virtual int cltSocketDestory(/*in*/) = 0;
//---------------第一套api接口-----End---------------//
};
#pragma once
//接口层
//加解密接口类
class CEncDesProtocol
{
public:
CEncDesProtocol(){;}
~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;
};
#pragma once
#include "SocketProtocol.h"
// socket产品类
// 继承接口,实现虚函数功能
class CSocketImp : public CSocketProtocol
{
public:
//客户端初始化 获取handle上下
int cltSocketInit(/*out*/);
//客户端发报文
int cltSocketSend(/*in*/ unsigned char* buf /*in*/, int buflen /*in*/);
//客户端收报文
int cltSocketRev(/*in*/ unsigned char* buf /*in*/, int* buflen /*out*/);
//客户端释放资源
int cltSocketDestory(/*in*/);
private:
unsigned char* buf; // 报文
int buflen; // 报文长度
};
#include "iostream"
using namespace std;
#include "SocketImp.h"
//客户端初始化 获取handle上下
int CSocketImp::cltSocketInit(/*out*/)
{
buf = NULL;
buflen = 0;
return 0;
}
//客户端发报文
int CSocketImp::cltSocketSend(/*in*/ unsigned char* buf /*in*/, int buflen /*in*/)
{
int ret = 0;
// 得到buf,分配内存
this->buf = new unsigned char[buflen];
if (this->buf == NULL)
{
ret = -1;
cout buf, buf, buflen);
this->buflen = buflen;
return ret;
}
//客户端收报文
int CSocketImp::cltSocketRev(/*in*/ unsigned char* buf /*in*/, int* buflen /*out*/)
{
int ret = 0;
if (buf == NULL || buflen == NULL)
{
ret = -1;
cout buf, this->buflen);
*buflen = this->buflen;
return ret;
}
//客户端释放资源
int CSocketImp::cltSocketDestory(/*in*/)
{
if (buf != NULL)
{
delete buf;
buf = NULL;
buflen = 0;
}
return 0;
}
#pragma once
#include "CEncDesProtocol.h"
// 加解密产品类
// 继承接口,实现虚函数功能
class CEncDesImp : 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 "EncDesImp.h"
#include "des.h"
// 加密
int CEncDesImp::EncData(unsigned char* plain, int plainlen, unsigned char* cryptdata, int* cryptlen)
{
int ret = 0;
ret = DesEnc(plain, plainlen, cryptdata, cryptlen);
if (ret != 0)
{
ret = -1;
cout
#define _CRT_SECURE_NO_WARNINGS
#include "iostream"
using namespace std;
#include "SocketImp.h"
#include "SocketProtocol.h"
#include "EncDesImp.h"
#include "CEncDesProtocol.h"
//面向抽象类编程,框架 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;
// 初始化 Socket
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;
}
//面向抽象类编程,框架 C++类实现
//继承:抽象类在多继承中的应用
/*
class SocketAndEncDec : public CSocketProtocol, public CEncDesProtocol
{
};
*/
// 组合
class SocketAndEncDec
{
public:
SocketAndEncDec()
{
this->sp = NULL;
this->ed = NULL;
}
SocketAndEncDec(CSocketProtocol* sp, CEncDesProtocol* ed)
{
this->sp = sp;
this->ed = ed;
}
// 注入思想
void setSp(CSocketProtocol* sp)
{
this->sp = sp;
}
void setEd(CEncDesProtocol* ed)
{
this->ed = ed;
}
// 框架成员函数
int SckSendAndRec_EncDec_adv(unsigned char* in, int inlen, unsigned char* out, int* outlen)
{
int ret = 0;
// 临时数据
unsigned char data[4096];
int datalen = 0;
// 初始化 Socket
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 = this->sp->cltSocketRev(data, &datalen);
if (ret != 0)
{
goto End;
}
// 对加密的数据进行解密
ret = this->ed->DecData(data, datalen, out, outlen);
if (ret != 0)
{
goto End;
}
End:
ret = this->sp->cltSocketDestory();
return 0;
}
private:
CSocketProtocol* sp;
CEncDesProtocol* ed;
};
//test
void main()
{
int ret = 0;
// 准备测试案例
unsigned char in[4096];
int inlen;
unsigned char out[4096];
int outlen = 0;
strcpy((char*)in, "TestSocketAndEncDes");
inlen = 10;
// 框架 C函数实现
{
// 父类指针指向子类对象,实现多态
CSocketProtocol* sp1 = NULL;
CEncDesProtocol* ed1 = NULL;
sp1 = new CSocketImp;
ed1 = new CEncDesImp;
// 使用接口
ret = SckSendAndRec_EncDec(sp1, ed1, in, inlen, out, &outlen);
if (ret != 0)
{
cout setEd(ed2);
mySAED->setSp(sp2);
ret = mySAED->SckSendAndRec_EncDec_adv(in, inlen, out, &outlen);
if (ret != 0)
{
cout
面向接口编程和C多态
函数类型
typedef int Func(int, int);
Func* pFunc;
int (*Func)(int, int);
void main()
{
// 定义一个数组类型 int a[10];
{
typedef int (myTypeArr)[10];
myTypeArr myArr;
myArr[0] = 10;
printf("myArr[0]: %d\n", myArr[0]);
}
// 定义一个数组指针类型
{
int a[10] = { 0 };
// 定义类型
typedef int (*pTypeArr)[10];
// 使用类型定义变量
pTypeArr myPArr;
// 使用变量
myPArr = &a;
// 使用数组指针 指向 a数组
(*myPArr)[0] = 20;
printf("a[0]: %d\n", a[0]);
}
system("pause");
return;
}
int add(int a, int b)
{
printf("func add result: %d\n", a+b);
return a + b;
}
void main()
{
// 定义一个函数类型 int add(int a, int b)
{
// 定义类型
typedef int (myTypeFunc)(int, int);
// 使用类型定义指针变量
myTypeFunc* pFunc = NULL;
// pFunc = &add; &可以省略
pFunc = add;
pFunc(1, 2); //间接调用
}
// 定义一个函数指针类型
{
typedef int(*myPTypeFunc)(int, int);
// 直接使用函数指针类型 定义 函数指针变量
myPTypeFunc pFunc = NULL;
pFunc = add;
pFunc(3, 4);
}
// 函数指针
{
// 直接定义函数指针变量
int (*myPFunc)(int, int);
myPFunc = add;
myPFunc(5, 6);
}
system("pause");
return;
}
函数指针做函数参数(回调函数)
// 假设是不同实现者 实现的功能
int add(int a, int b)
{
printf("func add result: %d\n", a+b);
return a + b;
}
int sub(int a, int b)
{
printf("func sub result: %d\n", a - b);
return a - b;
}
int mul(int a, int b)
{
printf("func mul result: %d\n", a * b);
return a * b;
}
// 定义一个函数指针类型
typedef int (*myPTypeFunc)(int, int);
// 操作者,任务的编写, 函数指针做函数参数
// int Operator(int (*myPTypeFunc)(int, int))
int Operator(myPTypeFunc myFunc)
{
int n = myFunc(1, 2); // 间接调用
return n;
}
//任务的调用
void main()
{
// 使用回调函数
Operator(add);
Operator(sub);
Operator(mul);
system("pause");
return;
}
函数指针正向调用
LoadLibrary、GetProcAddress
__declspec(dllexport) int myAdd(int a, int b);
__declspec(dllexport) int mySub(int a, int b);
__declspec(dllexport) int myMul(int a, int b);
__declspec(dllexport) int myDiv(int a, int b);
// 定义函数指针类型
typedef int(*myFunc)(int, int);
void main()
{
// 用函数指针类型 定义 函数指针变量
myFunc myAdd;
myFunc mySub;
myFunc myMul;
myFunc myDiv;
HINSTANCE hInstLibrary = LoadLibrary("c:/TestDLL.dll");
myAdd = (myFunc)GetProcAddress(hInstLibrary, "myAdd");
mySub = (myFunc)GetProcAddress(hInstLibrary, "mySub");
myMul = (myFunc)GetProcAddress(hInstLibrary, "myMul");
myDiv = (myFunc)GetProcAddress(hInstLibrary, "myDiv");
myAdd(1, 2);
mySub(2, 1);
myMul(1, 2);
myDiv(2, 1);
system("pause");
return;
}
案例:C动态库升级成框架