【问题标题】:Advice on Abstract Factory, DLL Exporting and Smart Pointers关于抽象工厂、DLL 导出和智能指针的建议
【发布时间】:2010-11-29 18:05:25
【问题描述】:

这是对我之前的一个问题的跟进,我已经为我的项目提出了一个可能的解决方案,如果我有这个权利,我需要一些建议或指导。

基本上我的项目是一个可以在 Linux 和 Windows 上使用和编译的库,Linux 部分不是什么大问题,它是 Windows。

我的库主要由类组成,因此 95% 的 C++ 代码。为了提供更好的支持并避免名称修改问题,我将使用接口和工厂方法来获取这些类的实例,而不是直接调用它。我还将在工厂函数上使用 extern "C" 来避免名称混淆。

以下是问题:

  1. 我将在工厂函数上使用导出/导入宏,但是我是否需要在我希望提供实例的所有类的头文件中添加导出/导入 (__declspec(dllexport/import)) 以包括基类接口?还是仅仅导出工厂函数就够了?

  2. 我也在考虑使用智能指针功能进行自动释放,好主意还是让用户处理?我打算使用 autoptr 模板,它是标准库的一部分,可在两个平台上使用,对吗?

  3. 谁能启发我应该使用哪种调用约定?我知道它是微软特有的,所以我希望它不会干扰 Linux,所以我应该把它留空,让它成为我认为是 _thiscall 或类似的东西的默认值。

  4. 我收到这段代码的错误,我不知道为什么,但这是由于 extern "C":

错误是:

错误:C 函数'std::ostream& operator

错误:C 函数 'std::ostream& operator

...这些错误消息在所有函数中重复

代码如下:

//WINLIB is my macro for the dllimport/export

extern "C"{

//operator overloading for stream operation
WINLIB std::ostream& operator<<(std::ostream &st, const SpeedInfo &si);
WINLIB std::ostream& operator<<(std::ostream &st, const MemInfo &mi);
WINLIB std::ostream& operator<<(std::ostream &st, const analyzed_result&);
WINLIB std::ostream& operator<<(std::ostream &st, const ustring_set&);
WINLIB std::ostream& operator<<(std::ostream &st, const speed_map&);
WINLIB std::ostream& operator<<(std::ostream &st, const mem_map&);

WINLIB SpeedInfo operator+(SpeedInfo &si, SpeedInfo &si2);
WINLIB SpeedInfo& operator+=(SpeedInfo &si, SpeedInfo &si2);
WINLIB SpeedInfo operator-(SpeedInfo &si, SpeedInfo &si2);
WINLIB SpeedInfo& operator-=(SpeedInfo &si, SpeedInfo &si2);

WINLIB MemInfo operator+(MemInfo &mi, MemInfo &mi2);
WINLIB MemInfo& operator+=(MemInfo &mi, MemInfo &mi2);
WINLIB MemInfo operator-(MemInfo &mi, MemInfo &mi2);
WINLIB MemInfo& operator-=(MemInfo &mi, MemInfo &mi2);
}

【问题讨论】:

    标签: c++ dll


    【解决方案1】:
    1. 导出工厂函数并在用户代码中包含类的标头就足够了。
    2. 如果您不依赖它,让用户为工作选择最适合的工具。
    3. __stdcall
    4. extern "C" 为您提供了 c 风格的声明范围 - 因此您不能在此处进行重载。见here。因为 win32 dll 也是 c 风格的,所以你不能直接导出重载函数(想想GetProcAddress())。

    【讨论】:

    • Alrite 完美,我将从所有类中获取所有 dllimport/export,并将仅在工厂函数中使用它。我想我也会使用 _stdcall 作为 windows 宏的一部分,最后一个问题,我应该只将 _stdcall 放在导出的工厂函数还是所有函数和类上?
    • 视情况而定。如果您只使用基本类型,纯虚拟方法就可以工作,否则就需要它。可以在 [此处][1] 找到一篇介绍类导出方法的好文章。 [1]:codeproject.com/KB/cpp/howto_export_cpp_classes.aspx
    • 好的,很抱歉由于缺少标记而造成的混乱。试试这篇文章:codeproject.com/KB/cpp/howto_export_cpp_classes.aspx
    • 是的,很棒的文章,我之前读过部分内容。我看到这家伙只在导出的函数上使用它,并使用预定义的宏来调用约定。也许我应该做一个 ifdef 宏检查是否定义了 APIENTRY 否则将其设为空白?
    • 虽然 APIENTRY 被简单地定义为 __stdcall,但如果你仍然包含 windows.h,我会在 windows 构建的导出宏中使用它。否则我会直接使用 __stdcall。
    【解决方案2】:

    关于你的工厂想法我不能说太多(这是> 10年前我做过这样的事情),但关于#4,你的错误信息:

    如果您将某些内容声明为extern "C",这意味着除其他外,该名称修改已关闭。但是名称修改不仅仅是一种麻烦,它的存在是有原因的。名称修饰意味着编译器将函数参数类型的名称修饰为函数名称,以便编译器和链接器可以区分重载函数。如果你将它们声明为extern "C",你又回到了 C 领域:编译器无法区分重载函数,因此重载不起作用。

    【讨论】:

    • 啊哈傻我完全忘记了 C 中的重载,谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-20
    • 2011-01-05
    • 1970-01-01
    • 1970-01-01
    • 2013-08-19
    相关资源
    最近更新 更多