近期在做项目时,需要把一个项目进行优化,最终完成模块化划分。考虑到C#中的三层架构,想用到VC中,由于VC对于分层的解决办法不是很好,就进行了折中处理,也就是进行项目的模块化划分,首先考虑到了接口的思想,但是VC中又没有接口的关键词interface,不过可以进行模拟转换,完成类似的接口功能,也就是使用纯虚函数,同时要结合工厂的思想来完成这个接口功能。项目是基于MFC的吗,在做测试实例的过程中,遇到了错误"LNK2019 无法解析的外部符号... public: static class ICEcgObject * __cdecl EcgObjectFactory::CreateEcgObject(void)" (? CreateEcgObject@EcgObjectFactory@@SAPAVICEcgObject@@XZ),该符号在函数 "protected: __thiscall CMainFrame::CMainFrame(void)" (? ? 0CMainFrame@@IAE@XZ) 中被引用,同时还有错误"LNK1120 ...个无法解析的外部命令"。查找相关资料,找了很多,不好解决,因为都不是网上说的原因,经过自己分析对比相关资料,最终找到了原因,因为在工厂类的定义中没有加"_declspec(dllexport)"造成的这个错误。
相关测试代码也贴出来供大家参考吧!
模拟接口头文件"IEcgObject.h"的定义
#pragma once #ifndef ICEcgObject_H #define ICEcgObject_H class ICEcgObject//相当于接口定义 { public: virtual ~ICEcgObject(void) {}; //从外面给局部变量传值 virtual void SetEcgParaValue(int g_iSampleRate, int g_iFilterType, int g_iPrecision) = 0; }; #endif
接口实现类"CEcgObject.h"的头文件
#pragma once #include "IEcgobject.h" class CEcgObject : public ICEcgObject { public: CEcgObject(); ~CEcgObject(); public: //从外面给局部变量传值 virtual void SetEcgParaValue(int g_iSampleRate, int g_iFilterType, int g_iPrecision); private: int _iSampleRate; //采样频率(只用于滤波) int _iFilterType; //滤波类型() int _iPrecision; };
接口实现类"CEcgObject.cpp"的源文件
#include "StdAfx.h" #include "EcgObject.h" CEcgObject::CEcgObject() { } CEcgObject::~CEcgObject() { } void CEcgObject::SetEcgParaValue(int g_iSampleRate, int g_iFilterType, int g_iPrecision) { _iSampleRate = g_iSampleRate; _iFilterType = g_iFilterType; _iPrecision = g_iPrecision; }
工厂类的头文件"EcgObjectFactory.h"的实现
#pragma once #include "EcgObject.h" //************************************ // Name: EcgObjectFactory.h // Desc:该工厂类实现了对某些产品的生产,通过公开的静态函数来完成(数据工厂,通过它调用对象类,返回给接口函数) // Return: // Args: // Others: 在MFC中,类前必须加入"_declspec(dllexport)"才能完成产品的生产,否则出现"LNK2019 无法解析的外部符",同时还有错误"LNK1120 ...个无法解析的外部命令"的产生 // Time:2016/8/26-11:19 // Author:shiminsheng //************************************ class _declspec(dllexport) EcgObjectFactory { EcgObjectFactory(); ~EcgObjectFactory(); public: static ICEcgObject *CreateEcgObject();//返回对象给ICEcgObject接口 static void DestroyEcgObject(ICEcgObject *ptr); };
工厂类的源文件"EcgObjectFactory.cpp"的实现
#include "stdafx.h" //*********************************************** // EcgObjectFactory.h // //*********************************************** #include "EcgObjectFactory.h" EcgObjectFactory::EcgObjectFactory() { } EcgObjectFactory::~EcgObjectFactory() { } ICEcgObject* EcgObjectFactory::CreateEcgObject() { return new CEcgObject; } void EcgObjectFactory::DestroyEcgObject(ICEcgObject *ptr) { delete ptr; }
以上是封装在DLL中的接口相关类的信息实现内容,下面看一下如何使用它,做如下测试,代码也是MFC的相关实现,在MFC的测试类"MFCApplication1Test.cpp"中,实现代码如下:
// MFCApplication1Test.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include "MFCApplication1Test.h" #include "../InterfaceECGTest/EcgObjectFactory.h" //包含类声明头文件 #ifdef _DEBUG #define new DEBUG_NEW #endif // 唯一的应用程序对象 CWinApp theApp; using namespace std; int main() { int nRetCode = 0; HMODULE hModule = ::GetModuleHandle(nullptr); if (hModule != nullptr) { // 初始化 MFC 并在失败时显示错误 if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0)) { // TODO: 更改错误代码以符合您的需要 wprintf(L"错误: MFC 初始化失败\n"); nRetCode = 1; } else { // TODO: 在此处为应用程序的行为编写代码。 ICEcgObject* p_EcgObject; p_EcgObject = EcgObjectFactory::CreateEcgObject(); p_EcgObject->InitParaValue(); p_EcgObject->SetEcgParaValue(10, 20, 30); EcgObjectFactory::DestroyEcgObject(p_EcgObject); } } else { // TODO: 更改错误代码以符合您的需要 wprintf(L"错误: GetModuleHandle 失败\n"); nRetCode = 1; } return nRetCode; }
以上就是实现的过程。同时附上相关源代码:实例源码(提取码:9f3c)