C++面向接口编程和C++多态

1函数类型语法基础
函数三要素: 名称、参数、返回值
C语言中的函数有自己特定的类型
C语言中通过typedef为函数类型重命名
typedef type name(parameter list)
typedef int f(int, int);
typedef void p(int);
函数指针
函数指针用于指向一个函数
函数名是函数体的入口地址
1)可通过函数类型定义函数指针: FuncType* pointer;
2)也可以直接定义:type (*pointer)(parameter list);
pointer为函数指针变量名
type为指向函数的返回值类型
parameter list为指向函数的参数类型列表
函数指针语法梳理
//函数类型
//函数指针类型
//函数指针变量

数组指针语法梳理
//数组类型语法
//数组指针类型
//数组指针变量

typedef int(FUNC)(int);

int test(int i)
{
return i * i;
}

void f()
{
printf(“Call f()…\n”);
}

int main()
{
FUNC* pt = test;
void(*pf)() = &f;
pf();
(*pf)();
printf(“Function pointer call: %d\n”, pt(3));
}

2函数指针做函数参数
1、指针做函数参数pk函数指针做函数参数
回忆指针做函数参数
一级指针做函数参数、二级。。。。、三级
2、函数指针做函数参数
当函数指针 做为函数的参数,传递给一个被调用函数,
被调用函数就可以通过这个指针调用外部的函数,这就形成了回调
3、练习
int add(int a, int b)
int libfun( int (*pDis)(int a, int b) );

int main(void)
{
int (*pfun)(int a, int b);
pfun = add;
libfun(pfun);

}

int add(int a, int b)
{
return a + b;

}

int libfun( int (*pDis)(int a, int b) )
{
int a, b;
a = 1;
b = 2;
add(1,3) //直接调用add函数
printf("%d", pDis(a, b)); //通过函数指针做函数参数,间接调用add函数
//思考 这样写 pDis(a, b)有什么好处?
}
//剖析思路
//1函数的调用 和 函数的实现 有效的分离
//2 C++的多态,可扩展

现在这几个函数是在同一个文件当中
假如
int libfun(int (*pDis)(int a, int b))
是一个库中的函数,就只有使用回调了,通过函数指针参数将外部函数地址传入
来实现调用

函数 add 的代码作了修改,也不必改动库的代码,就可以正常实现调用
便于程序的维护和升级
回调函数思想:
在这里插入图片描述
结论:回调函数的本质:提前做了一个协议的约定(把函数的参数、函数返回值提前约定)
请思考:C编译器通过那个具体的语法,实现解耦合的?
C++编译器通过多态的机制(提前布局vptr指针和虚函数表,找虚函数入口地址来实现)
3函数指针正向调用
1、函数指针做函数参数,调用方式
被调用函数和主调函数在同一文件中(用来教学,没有任何意义)
2、函数指针做函数参数
被调用函数和主调函数不在同一个文件中、模块中。
难点:理解被调用函数是什么机制被调用起来的。框架
框架提前设置了被调用函数的入口(框架提供了第三方模块入口地址的集成功能)
框架具备调用第三方模块入口函数
3、练习

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

int MyEncDataFunc(unsigned char *inData,int inDataLen,unsigned char *outData,int *outDataLen,void *Ref, int RefLen)
{
int rv = 0;
char *p = “222222222222”;
strcpy(outData, p);
*outDataLen = strlen§;
return rv;
}

int Send_Data(EncDataFunc encDataFunc, unsigned char *inData, int inDataLen, unsigned char *outData, int *outDatalen)
{
int rv = 0;
if (encDataFunc != NULL)
{
rv = encDataFunc(inData, inDataLen, outData, outDatalen, NULL, 0);
if (rv != 0)
{
printf(“func encDataFunc() err.\n”);
return rv;
}
}
return rv;
}

int main()
{
int rv = 0;
EncDataFunc encDataFunc = NULL;
encDataFunc = MyEncDataFunc;
// 第一个调用
{
unsigned char inData[2048];
int inDataLen;
unsigned char outData[2048];
int outDatalen;
strcpy(inData, “1111”);
inDataLen = strlen(inData);
rv = encDataFunc(inData,inDataLen, outData, &outDatalen, NULL, 0);
if (rv != 0)
{
printf(“edf err …\n”);
}
else
{
printf(“edf ok \n”);
printf("%s \n", outData);
}
}
{
unsigned char inData[2048];
int inDataLen;
unsigned char outData[2048];
int outDatalen;
strcpy(inData, “3333”);
inDataLen = strlen(inData);
rv = Send_Data(MyEncDataFunc, inData, inDataLen, outData, &outDatalen);
if (rv != 0)
{
printf(“func Send_Data err:%d”, rv);
return rv;
}
printf("%s \n", outData);
}
getchar();
}
4函数指针反向调用
回调函数效果展示。
5.C动态库升级成框架案例
C语言版本Socket动态库升级成框架集成第三方产品
简称:C动态库升级成框架案例
名字解释
动态库:抽象类一个套接口,单独封装成模块,供别人调用;无法扩展。
框架:能自由的扩展

案例背景:一般的企业信息系统都有成熟的框架,可以有C语言写,也可以由C++语言。软件框架一般不发生变化,能自由的集成第三方厂商的产品。

案例需求:在socket通信库中,完成数据加密功能,有n个厂商的加密产品供你选择,如何实现动态库和第三个厂商产品的解耦合。
提醒:C++通过抽象类,也就是面向抽象类编程实现的(相当于C++编译器通过多态机制,已经很好用了。提前布局vptr指针、虚函数表;调用是迟绑定完成。),
C语言中如何实现哪?

案例要求: 1)能支持多个第三方厂商加密产品的入围
2)企业信息系统框架不轻易发生框架
需求实现思路分析
在这里插入图片描述
思考1:企业信息系统框架、第三方产品如何分层
思考2:企业信息系统框架,如何自由集成第三方产品
(软件设计:模块要求松、接口要求紧)
思考3:软件分层确定后,动态库应该做什么?产品入围厂商应该做什么?
以后,开发企业信息系统框架的程序员,应该做什么?
第三方产品入围应该做什么?
编码实现

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、动态库中可以缓存第三方函数的入口地址,也可以不缓存,两种实现方式。
案例总结
回调函数:利用函数指针做函数参数,实现的一种调用机制,具体任务的实现者,可以不知道什么时候被调用。
回调机制原理:
当具体事件发生时,调用者通过函数指针调用具体函数
回调机制的将调用者和被调函数分开,两者互不依赖
任务的实现 和 任务的调用 可以耦合 (提前进行接口的封装和设计)

猜你喜欢

转载自blog.csdn.net/it_xiangqiang/article/details/109114399