近期在做项目时,需要把一个项目进行优化,最终完成模块化划分。考虑到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)