【问题标题】:dllexport an all-inline class?dllexport 一个全内联类?
【发布时间】:2012-11-06 13:59:57
【问题描述】:

考虑一个简单的类,它只包含内联的成员函数。例如:

template <typename T1, typename T2>
class Point2D {
public:
    typedef Point2D<T1,T2> ThisType;
    typedef T1 Tx;
    typedef T2 Ty;
    T1 x;
    T2 y;
    inline Point2D() : x(0), y(0) {}
    inline Point2D(T1 nx, T2 ny) : x(nx), y(ny) {}
    inline Point2D(const Point2D& b) : x(b.x), y(b.y) {}
    inline Point2D& operator=(const Point2D& b) { x=b.x; y=b.y; return *this; }
    inline ~Point2D() {}
};

typedef Point2D<int,int> Int2;

当我想导出到 DLL 的另一个类(例如,MyClass,成员 Int2 point)中使用类型为 Int2 的对象时,我收到以下警告:

警告 C4251:“MyClass::point”:“Point2D”类需要有 dll 接口才能供“MyClass”类的客户端使用

但是,如果我按照警告提示将__declspec(dllexport) 放入“Point2D”的定义中(这对我来说似乎很愚蠢,因为所有函数都是内联的,而且它是一个模板,see SO question),我会得到以下信息尝试在另一个项目中使用 DLL 时出错:

错误 LNK2019:无法解析的外部符号“__declspec(dllimport) public: __thiscall lwin::Point2D::Point2D(int,int)” ...

注意,Point2D 的定义在所有项目可见的标题中给出。

我该怎么办?跳过dllexport 并忽略警告?还是有一些巧妙的技巧可以避免这种编译器混淆?

【问题讨论】:

  • 您收到警告是因为您忘记了编译器自动生成的复制构造函数和赋值运算符。只需将它们添加到类或忽略警告。
  • 好收获!固定的。但问题依然存在……

标签: c++ visual-c++ dll dllexport


【解决方案1】:

MyClassInt2 成员替换为Int2* 成员以解决此问题。在MyClass构造函数中创建Int2实例,在MyClass析构函数中删除。

无法导出模板类,因此不能将其声明为__declspec(dllexport)。显示 C4251,因为容器类大小可能不同,如果 Dll 及其客户端使用不同的编译选项进行编译,则会导致未定义的行为。另一方面,指针始终具有相同的大小。

【讨论】:

  • 如果我将所有Int2 替换为Int2*(和类似的),使用newdelete,那最终将是一个很大的性能损失!没有办法解决这个问题?
  • 不幸的是,这是我知道解决此问题的唯一方法。只有当 Dll 及其所有客户端始终作为某个系统的一部分编译在一起时,您才能忽略此警告。当然,使用相同的编译器选项。
  • @Alex:无论如何导出的类都需要它。
  • @Ben Voigt - 你是说忽略这个警告吗?好吧,我从来没有在自己的项目中这样做过,可能这个建议是不正确的。
  • 如果没有更好的解决方案,如果性能很关键,我会用非模板类替换 Point2D。
【解决方案2】:

尝试将__declspec(dllexport) / __declspec(dllimport) 分别添加到每个内联方法中。对于非模板类,这将是一个错误,但模板类/函数似乎也需要添加此 per-method。

【讨论】:

    猜你喜欢
    • 2012-08-09
    • 2012-02-11
    • 2023-03-28
    • 2016-02-18
    • 1970-01-01
    • 2011-06-12
    • 2014-07-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多