前言
之前在用Windows API 实现添加任务计划的时候,用到了COM组件,COM组件的使用和Windows API截然不同,COM组件的使用是通过接口得到对象,来使用对象的各种方法,这种面向对象的方式我感觉很方便,一个接口,实现一个功能。
经过搜索资料了解到,COM思想是定义一个抽象类(都是纯虚函数),然后调用者和dll共用同一个抽象类的头文件(dll根据这个抽象类来实现派生类)以及这种方式写出来的dll接口通用性很强
两个月前学了C++都没咋用过,我觉得是时候来实践实践了哈哈哈
这样简单描述对新人(比如我)来说肯定不会很明白的,接下来举例子来讲解
代码示例
这里制作一个简易计算器功能来讲解:通过封装一个接口来实现计算器的加减乘除基本功能:
export_Test.h: 共用的头文件
#ifdef EXPORTTEST_EXPORTS
#define EXPORTTEST_API __declspec(dllexport)
#else
#define EXPORTTEST_API __declspec(dllimport)
#endif
//要作为接口方法导出的函数写成虚函数,写在抽象类里
//其他内部实现在类内定义进行即可
//一个接口一个功能
class Calu1 {
public:
virtual int add(int n1, int n2) = 0;
virtual int sub(int n1, int n2) = 0;
virtual void delObject() = 0;
};
//通过工厂函数获得这个类,不同抽象类的工厂函数名称不能相同
//使用抽象基类作为函数类型,是因为这样一来,只有基类的函数被导出了
//其余功能函数对外不可见,仅用于内部调用
//从而实现接口与实现分离
extern "C" EXPORTTEST_API Calu1 * GetObj1();
class Calu2 {
public:
virtual int mul(int n1, int n2) = 0;
virtual int div(int n1, int n2) = 0;
virtual void delObject() = 0;
};
//导出函数是一个 返回值为Calu2指针类型的函数,也就是对象指针
extern "C" EXPORTTEST_API Calu2 * GetObj2();
这里把计算器拆成两半了,主要是想尝试一下多个接口要如何并存。
从入门体验上来说,一个接口类对应一个工厂函数(创建对应派生类的函数),一个接口用来实现一个功能,一个派生类可以继承多个类,其中一个是接口类就行
export_Test.cpp: 功能实现
#include "export_Test.h"
#include <iostream>
using namespace std;
//公共用的类就单独定义基类,让接口派生类来继承
class ShowRes {
public:
void PrintRes(int x) {
cout << x << endl;
}
};
class TwoNum :public Calu1 {
public:
TwoNum() {
cout << "Object is Created!"<< endl;
}
~TwoNum() {
cout << "Object is Deleted!" << endl;
}
virtual int add(int n1, int n2) {
int res = n1 + n2;
cout <<n1<<" + "<<n2<< " = " << res << endl;
return res;
}
virtual int sub(int n1, int n2) {
int res = n1 - n2;
cout << n1 << " - " << n2 << " = " << res << endl;
return res;
}
virtual void delObject() {
delete this;
}
};
extern "C" EXPORTTEST_API Calu1 * GetObj1() {
return new TwoNum;
}
/// ///////////////////////////////////////////////////
class TwoNummd :public Calu2 ,public ShowRes{
public:
TwoNummd() {
cout << "Object is Created!" << endl;
}
~TwoNummd() {
cout << "Object is Deleted!" << endl;
}
virtual int mul(int n1, int n2) {
int res = tmpmul(n1, n2);
cout << n1 << " * " << n2 << " = " << res << endl;
return res;
}
virtual int div(int n1, int n2) {
int res = n1 / n2;
cout << n1 << " - " << n2 << " = ";
PrintRes(res);
return res;
}
virtual void delObject() {
delete this;
}
int tmpmul(int n1, int n2) {
return n1 * n2;
}
};
Calu2* GetObj2()
{
return new TwoNummd;
}
就是接口类的纯虚函数的简单实现,没啥说的
Test.cpp: 调用测试
#include <iostream>
using namespace std;
#include "export_Test.h"
#pragma comment(lib,"exportTest.lib")
int main()
{
Calu1* p = GetObj1();
p->add(66,5);
p->sub(72,60);
Calu2* n = GetObj2();
n->mul(5, 9);
n->div(1024, 222);
system("pause");
std::cout << "Hello World!\n";
}
新建一个控制台项目来调用刚刚写的接口类,从调用者的角度来看,这个计算器的类提供了计算的功能,直接调用就行,很方便的感觉