关于抽象工厂,DLL导出和智能指针的建议

时间:2009-09-19 16:47:33

标签: c++ dll

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

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

我的库主要由类组成,所以95%的C ++代码。为了提供更好的支持并避免名称错位问题,我将使用接口和工厂方法来获取这些类的实例,而不是直接调用它们。我还将在工厂功能上使用extern“C”以避免名称损坏。

以下是问题:

  1. 我将在工厂函数上使用导出/导入宏,但是我是否需要在我希望提供的所有类的头文件中添加导出/导入(__declspec(dllexport / import))包含基类接口的实例?或者只是简单地导出工厂功能?

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

  3. 任何人都可以启发我应该使用哪种调用约定?我知道它特定于微软,所以我希望它不会干扰Linux,所以我应该把它留空并让它成为我认为是_thiscall的默认设置或类似的东西。

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

  5. 错误是:

      

    错误:C函数'std :: ostream&的声明运算符<<(std :: ostream&,const MemInfo&)'与|冲突先前的声明'std :: ostream&运算符<<(std :: ostream&,const SpeedInfo&)'here |

         

    错误:C函数'std :: ostream&的声明运算符<<(std :: ostream&,const analyze_result&)'与之前的声明'std :: ostream&运算符<<(std :: ostream&,const MemInfo&)'here |

    ...对所有功能重复这些错误消息

    以下是代码:

    //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);
    }
    

2 个答案:

答案 0 :(得分:1)

  1. 导出工厂功能并在用户代码中包含类的标题就足够了。
  2. 如果您不依赖它,请让用户选择他最适合的工具。
  3. __ STDCALL
  4. extern“C”为您提供了一个c风格的声明范围 - 因此您不能在那里超载。见here。因为win32 dll也是c风格,你不能直接导出重载函数(想想GetProcAddress())。

答案 1 :(得分:1)

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

如果您将某些内容声明为extern "C",则在某些其他方面,这意味着名称修改已关闭。但名称错误不仅仅是一种麻烦,它有一个原因。名称修改意味着编译器会将函数参数类型的名称变为函数名称,以便编译器和链接器可以相互告知重载函数。如果你将它们声明为extern "C",那么你就会回到C盘:编译器不能告诉彼此重载的函数,因此重载不起作用。