您有幾種可供選擇的選項。我將在這裏給出2個選項,其中DLL的客戶端可以完全控制它使用的MyClass
實例的生命週期,儘管客戶端並不知道它實際上是MyClass
實例。
假設您公開的DLL功能被公開爲Flubber。第一個選項是,你與含有這種公共的頭文件Flubber.h提供您的DLL:
#ifdef FLUBBER_EXPORTS
#define FLUBBER_API __declspec(dllexport)
#else
#define FLUBBER_API __declspec(dllimport)
#endif
typedef struct FlubberHandle_* FlubberHandle;
FLUBBER_API FlubberHandle CreateFlubber();
FLUBBER_API void DestroyFlubber(FlubberHandle flubber);
FLUBBER_API void SetFlubberNumber(FlubberHandle flubber, int number);
實施看起來是這樣的:
#include "Flubber.h"
class MyClass
{
public:
void SetNumber(int x){ _number = x;}
private:
int _number;
};
struct FlubberHandle_
{
MyClass impl;
};
FLUBBER_API FlubberHandle CreateFlubber()
{
return new FlubberHandle_;
}
FLUBBER_API void DestroyFlubber(FlubberHandle flubber)
{
delete flubber;
}
FLUBBER_API void SetFlubberNumber(FlubberHandle flubber, int number)
{
flubber->impl.SetNumber(number);
}
當你建立你的DLL,定義FLUBBER_EXPORTS
宏。當客戶端使用的DLL,它必須做不一樣的,只是引用的DLL導入庫(Flubber.lib)和包括Flubber.h頭:
#include <Flubber.h>
int main()
{
FlubberHandle flubberHandle = CreateFlubber();
... // Do lots of other stuff before setting the number
SetFlubberNumber(flubberHandle, 4711);
... // Do even more stuff and eventually clean up the flubber
DestroyFlubber(flubberHandle);
return 0;
}
這讓DLL客戶端的最簡單方法控制暴露某些功能的實例的生命週期。
但是,通過將FlubberHandle
管理「包裝回」到正確的RAII類中,爲您的DLL客戶端提供更豐富的接口並不需要太多努力。如果「隱藏」 MyClass
類暴露許多其他的公共的事情,你仍然可以選擇只公開你在導出的自由函數(CreateFlubber
,DestroyFlubber
和SetFlubberNumber
)和RAII類選擇什麼:
#ifdef FLUBBER_EXPORTS
#define FLUBBER_API __declspec(dllexport)
#else
#define FLUBBER_API __declspec(dllimport)
#endif
typedef struct FlubberHandle_* FlubberHandle;
FLUBBER_API FlubberHandle CreateFlubber();
FLUBBER_API void DestroyFlubber(FlubberHandle flubber);
FLUBBER_API void SetFlubberNumber(FlubberHandle flubber, int number);
class Flubber final
{
FlubberHandle m_flubber;
public:
Flubber() : m_flubber(CreateFlubber()) {}
Flubber(const Flubber&) = delete;
Flubber& operator=(const Flubber&) = delete;
~Flubber() { DestroyFlubber(m_flubber); }
void SetNumber(int number) { SetFlubberNumber(m_flubber, number); }
};
使用RAII類,你的DLL和其API的客戶體驗將大大改善:
#include "stdafx.h"
#include <Flubber.h>
int main()
{
Flubber flubber;
... // Do lots of other stuff before setting the number
flubber.SetNumber(4711);
return 0;
}
這最後一種方法是通過Stefanus迪圖瓦創造「沙漏接口」(他的演講「沙漏接口,用於C++的API」在CppCon 2014可用在線在https://www.youtube.com/watch?v=PVYdHDm0q6Y),而且很簡單你有一個在底部有一個「胖」/完整/豐富的C++實現的庫。您可以通過精簡的C函數層將其功能展示給庫客戶端。最重要的是,您還可以通過將C函數包裝在適當的(通常是RAII)包裝類中,將豐富的C++接口分發到您公開的功能。
第三個選項是不透明接口;例如一個函數返回類的一個新實例強制轉換爲'HANDLE',並在DLL中使用'HANDLE'作爲參數並通過它調用類方法的幫助器函數(顯然還有一個函數釋放了'HANDLE' )。 –
作爲一個單身人士是一個階級的固有屬性。它不取決於你是否想用特定的技術公開它的方法。如果它本質上是一個單身人士,那麼繼續將它編程爲一個單身人士。至於你的第二個想法,它基本上是「讓我們以一種非常模糊和迂迴的方式來創建一個單身人士」。 –