0

我试图通过导出为 DLL(在 Windows/VS 2010 上)来保护一些 C++ 代码。

在下面的示例中var,在超类构造函数中设置,调试器显示它肯定设置为引用something

测试是在使用包含测试类的 DLL 的代码中构建的。

但是当go从 test 的实例上调用时(从 DLL 调用,但调用方法由 DLL 使用者调用)var是一个空指针(它的值为 0)。

这是一种简化,因为我不允许共享实际代码。

//Headers

class Base {
  public:
    __declspec(dllexport) Base();      
  private:
    Foo* var;
};

class Test : Base {
public:
  __declspec(dllexport) Test();
  __declspec(dllexport) void go();
private:
};

//Body

Base::Base() {
  var = new Foo();
}

Test::Test() : Base() {
}

void Test::go() {
  var->do_something();
}

在消费代码中,标头是

class Base {
public:
  __declspec(dllimport) Base();
}; 

class Test {
public:
  __declspec(dllimport) Test();
  __declspec(dllimport) void go();
};

实际的代码要复杂得多,但如果有人能告诉我是否有已知限制使用 dllexport 的实例变量,或者我更有可能在空指针上调用 Test 的方法,或者也许这是一个 dllexport 和继承问题。此代码在我拆分消费者代码之前有效,并且 DLL 代码在同一个项目中,它只是在拆分后才中断,我想将 dllexporting/dllimporting 函数公开到消费者使用的第二组标头中。

4

3 回答 3

1

当您Test在“消费代码”中将值从一个地方传递到另一个地方时,您将导致切片发生,因为客户端代码不知道该变量并为 class 计算了不正确的大小Test

为了解决这个问题,您也应该在客户端代码中声明变量,或者您可以提供某种静态工厂函数,只允许客户端代码传递指向Tests 的指针以避免切片。

于 2012-02-08T22:37:12.060 回答
0

如果您从提供给客户的代码中删除实例变量,则只有您自己的代码知道对象的实际大小并可以创建它。从我的脑海中,你有两种方法可以解决这个问题:

  1. 提供一个 createTest 静态函数来创建您的类的实例(工厂方法)。这里最好的做法是提供一个纯接口(没有实例变量)。

  2. 如果您只想隐藏课程的特定部分,您可以使用 pimpl idiom(维基百科文章)。

于 2012-02-08T22:47:48.297 回答
0

有什么理由不使用:

#ifdef IN_FOO_PROJECT
# define fooEXPORT __declspec(dllexport)
#else
# define fooEXPORT __declspec(dllimport)
#endif

class fooEXPORT exportClass
{
public:
  void function( void );
  Foo * var;
}

如果您想隐藏您的班级(或班级的一部分),您可以将其用作私人成员:

#ifdef IN_FOO_PROJECT
# define fooEXPORT __declspec(dllexport)
#else
# define fooEXPORT __declspec(dllimport)
#endif

class classToHide;

class fooEXPORT exportClass
{
public:
  void function( void );
  classToHide * var;
}

在 Cpp 中:

#include "exportClass.h"
#include "classToHide.h"

void exportClass::function( void )
{
  var->function();
}
于 2012-02-09T15:15:20.420 回答