C++中级(一) C++实现接口:先普及成员变量初始化、虚函数。然后阐述用DLL工程对接口的定义、实现、导出。最后建立一个控制台工程使用该接口。

 

一、简介

本博客主要介绍 C++实现接口,但是在普及接口问题之前,还将拓展成员变量初始化、虚函数,因为成员变量初始化、虚函数是实现接口的基础。

二、成员变量初始化

成员变量的初始化,只要看这篇博客够了https://blog.csdn.net/yu132563/article/details/80103887

方法1:

class Animal  
{  
public:  
    Animal(int weight,int height):       //A初始化列表  
      m_weight(weight),  
      m_height(height)  
    {  
    }   
private:  
    int m_weight;  
    int m_height;  
};  

方法2:

class Animal  
{  
public:   
    Animal(int weight,int height)       //B函数体内初始化  
    {  
        m_weight = weight;  
        m_height = height;  
    }  
private:  
    int m_weight;  
    int m_height;  
};  

三、虚函数

什么是虚函数?接口函数的定义?什么要用虚函数。

参考:

https://www.cnblogs.com/xudong-bupt/p/3570304.html

https://www.cnblogs.com/azbane/p/7267079.html

C++的虚函数主要作用是“运行时多态”,父类中提供虚函数的实现,为子类提供默认的函数实现。说白了,A类定义了虚函数,B想怎么实现这个虚函数都行(实际上就是多态,多态性是将接口与实现进行分离)。

四、接口

(1)、方法1 —— 主要参考:https://www.cnblogs.com/KunLunSu/p/6443882.html

新建一个C++的DLL工程,命名为InterfaceDefineAndRealize:

不懂建立DLL的话,请参考 C++ 基础(五)使用vs2015封装c++生成.dll文件、.lib文件、.h文件后,给另一个工程使用:使用前,需配置头文件(.h)静态库(.lib)和 动态库(.dll )项目属性

1、接口的定义:放在头文件 InterfaceDefineAndRealize.h中。

#ifndef INTERFACE_DEFINE_AND_REALIZE  
#define INTERFACE_DEFINE_AND_REALIZE  

#include <string>  
using namespace std;
 
class Person
{
public:
	Person() : m_StrName("###") //将成员变量  m_StrName 初始化为 ### 
	{ };
	virtual ~Person() {};
	virtual void Eat() = 0;//人需要吃东西  
	virtual void Sleep() = 0;//人需要睡觉  
	virtual void SetName(const string strName) = 0;//人都有名字  
	virtual string GetName() = 0;//获取名字  
	virtual void Work() = 0;    //人可能要有工作  
private:
	string m_StrName;
};
//实现接口  
//实现接口是通过派生类实现的,每个派生类依据自身特点,可以获取同一接口的不同实现  
//也就是所谓的多态  
class Student :public Person
{
public:
	Student() :m_strName("***")
	{ };
	~Student()
	{ };
	void Eat();
	void Sleep();
	void SetName(const string strName);
	string GetName();
	void Work();
private:
	string m_strName;
};

#endif 

上面的接口,带有一个Student类来实现,如果你把Student类也可以。

#ifndef INTERFACE_DEFINE_AND_REALIZE  
#define INTERFACE_DEFINE_AND_REALIZE  

#include <string>  
using namespace std;
 
class Person
{
public:
	Person() : m_StrName("###") //将成员变量  m_StrName 初始化为 ### 
	{ };
	virtual ~Person() {};
	virtual void Eat() = 0;//人需要吃东西  
	virtual void Sleep() = 0;//人需要睡觉  
	virtual void SetName(const string strName) = 0;//人都有名字  
	virtual string GetName() = 0;//获取名字  
	virtual void Work() = 0;    //人可能要有工作  
private:
	string m_StrName;
};

#endif 

 此时,该接口不带任何实现,只是定义了而已。

2、接口的实现:在InterfaceDefineAndRealize.cpp中实现

好了,我们刚才在头文件中,定义了接口的方法体,现在,我们在InterfaceDefineAndRealize.cpp实现该方法体。

#include "InterfaceDefineAndRealize.h"  
#include <iostream>  
#include <string> 
 
using std::string;  
using std::cout;  
using std::endl;  
  
//接口的外部实现  
void Student::Sleep()  
{  
    cout<<"student sleep."<<endl;  
}  
void Student::Eat()  
{  
    cout<<"student eat."<<endl;  
}  
void Student::SetName(const string strName)  
{  
    m_strName=strName;  
}  
void Student::Work()  
{  
    cout<<"student work."<<endl;  
}  
string Student::GetName()  
{  
    return m_strName;  
}  
//需要导出的函数,即用户在外部可以调用的接口  
_declspec(dllexport)bool GetPersonObject(void** _RtObject)  
{  
    Person* pMan=NULL;  
    pMan=new Student();  
    *_RtObject=(void*)pMan;  
    return true;  
}  

3、接口的导出:在InterfaceDefineAndRealize.def模块文件中完成

LIBRARY InterfaceDefineAndRealize  
EXPORTS  
GetPersonObject  

4、接口的使用:

接口已经用DLL工程定义好了,现在是要使用该接口了。新建一个C++控制台工程(注意不是DLL工程),命名为AAA。

工程目录截图:

工程文件夹截图:

注意到include文件夹放接口的头文件,lib文件夹放接口的.lib文件——这是标准的写法。

添加刚才的DLL文件相关文件进去,关于如何添加指定目录的指定文件,请参考:

原 C++ 基础(五)使用vs2015封装c++生成.dll文件、.lib文件、.h文件后,给另一个工程使用:使用前,需配置头文件(.h)静态库(.lib)和 动态库(.dll )项目属性

https://www.cnblogs.com/KunLunSu/p/6443882.html

https://blog.csdn.net/xpj8888/article/category/8525582

AAA.CPP文件:

#include <iostream>  
#include "InterfaceDefineAndRealize.h"  
bool _declspec(dllimport) GetPersonObject(void** _RtObject);  
int main()  
{  
    Person* person=NULL;  
    void* pObj=NULL;  
    if(GetPersonObject(&pObj))//调用接口  
    {  
        person=(Person*)pObj;  
        person->Eat();  
        person->Sleep();  
        person->SetName("zhang hui");  
        std::cout<<person->GetName()<<std::endl;  
        person->Work();  
  
        if(person!=NULL)  
        {  
            delete person;  
            person=NULL;  
        }  
    }  
    system("pause");  
    return 0;  
}  

5、运行结果:

(2)方法2——只需要建立三个.cpp文件即可,不需要建立.h和.def文件

在方法1中,需要.cpp文件、.h文件和.def文件,但是,这篇博客提供了用三个.cpp文件可以实现接口的方法。

https://www.cnblogs.com/xiaocaocao/p/8451838.html

(3)方法3——先定义接口的别名,然后谁都可以用这个接口(这是最常用的方式)

https://blog.csdn.net/GVFDBDF/article/details/52204240

https://www.cnblogs.com/nzbbody/p/3448385.html

https://www.cnblogs.com/nzbbody/p/3448385.html往往在头文件中,定义接口),但是方法1,是在.cpp文件中定义接口。

比如

#define EXPORT_API __declspec(dllexport)
typedef void(__stdcall *COMCommandCallBackEvent)(int command, char *val);

// 接口
EXPORT_API int __stdcall TimerBoardOpen(void);     //时序板打开接口,成功返回1   失败返回0 
EXPORT_API int __stdcall TimerBoardClose(void);    //时序板关闭接口, 成功返回1   失败返回0
EXPORT_API void __stdcall TimerBoardSetParam(long Command, char *chVal); //设置参数命令接口(命令如下列表,chVal 需要设置的值)
EXPORT_API void __stdcall TimerBoardSetComCallBack(COMCommandCallBackEvent ICall); //设置回调数据接口

其中,__stdcall表示默认使用Win32系统。https://blog.csdn.net/qq_15267341/article/details/79995021

四、分析接口的关键字

(1)方法1中:分析方法1中的关键字

我们注意到,在DLL工程的InterfaceDefineAndRealize.cpp文件,有如下的代码:

_declspec(dllexport)bool GetPersonObject(void** _RtObject)
{
	Person* pMan = NULL;
	pMan = new Student();
	*_RtObject = (void*)pMan;
	return true;
}

类似的,在AAA工程的AAA.CPP文件中,也有类似的代码:

bool _declspec(dllimport) GetPersonObject(void** _RtObject);

好了,我们现在来分析接口的关键字 

好了,我们现在来分析接口的关键字

好了,我们现在来分析接口的关键字

参考:https://blog.csdn.net/GVFDBDF/article/details/52204240

_declspec(dllexport)  ——声明输出接口的关键字

_declspec(dllimport)  ——声明输入接口的关键字

_declspec(dllexport)bool ——输出接口为bool型

bool _declspec(dllimport) ——输入接口为bool型

 GetPersonObject(void** _RtObject) ——接口的名字及其参数

(2)_declspec(dllexport) 与 __declspec(dllexport)  

_declspec(dllexport)  :关键字declspec前带了一杠。

__declspec(dllexport)  :关键字declspec前带了两个杠。

但是两个的含义以及效果,是一样的。

五、总结

1、本博客,主要参考https://www.cnblogs.com/KunLunSu/p/6443882.html

2、如果你想要看看接口是用来干嘛的,你可以点击我博客的链接进去,我参考的博客,大部分已经说明接口的应用了。

猜你喜欢

转载自blog.csdn.net/xpj8888/article/details/85274345
今日推荐