我当前正在处理一个使用DLL和使用DLL的应用程序的项目。像往常
---- TaskInterface.h ----
class Task {
public:
virtual int func1(void) = 0;
virtual int func2(void) = 0;
};
extern "C" __declspec(dllexport) Task * APIENTRY newTask();
--- Task.h ---
class TaskImpl : public Task
{
public:
virtual int func1(void);
virtual int func2(void):
};
Task * APIENTRY newTask()
{
return static_cast<Task*>( new TaskImpl );
}
--- Task.cpp ---
int TaskImpl::func1(void)
{
// ...
}
int TaskImpl::func2(void)
{
// ...
}
这在预期的情况下起作用,应用程序包括" AbstractTask.h",然后调用由类TaskImpl定义的相应函数:
--- TheApplication.cpp ---
Task aTask = newTask();
aTask->func1();
aTask->func2();
// ...
但是,现在该应用程序发现类TaskImpl中的默认实现不够,因此在其自己的范围内定义了一个新的派生类,例如:
--- AppImpl.h ---
#include "TaskInterface.h"
class AppImpl : public Task
{
int func1(void) = { /* new stuff */ }
int func2(void) = { /* new stuff */ }
};
然后在theapplication.cpp中定义:
--- TheApplication.cpp ---
#include "AppImpl.h"
ApplImp * aNewTask = static_cast<Task*>(newTask());
aNewTask->func1();
aNewTask->func2();
您认为func1()和func2()被调用?正确:它仍然是DLL类TaskImpl内部的具体实现,而不是Class Appimpl定义的派生。
基本上这是我的问题:我想从DLL内部使用默认实现,但是我希望能够在应用程序端将其扩展,因此,除非我明确地超过了Applimp.h中的功能,否则回到dll内部定义的一个。
这可能吗?如果是这样,我在做什么错?如果没有,我该如何完成同等的事情?
我已经在导出" taskInterface.h"one_answers" task.h",然后让Applimp.h在DLL中包含混凝土类,但是由于明显的原因,该编译不喜欢它=>无法导出NewTask()两次。
任何帮助都将受到赞赏!
您需要通过dll分配和Deallocation ,我建议您与DLL一起提供包装类。然后,该包装类可以设计为继承。
class Task {
public:
virtual int func1(void) = 0;
virtual int func2(void) = 0;
};
// v~~~~v probably dllimport in the header you ship
extern "C" __declspec(dllexport) Task * APIENTRY newTask();
class TaskWrapper {
public:
TaskWrapper() : m_ptr( newTask() ) {}
virtual ~TaskWrapper() { deleteTask(m_ptr); }
virtual int func1(void) { m_ptr->func1(); }
virtual int func2(void) { m_ptr->func2(); }
protected: // implementation omitted for brevity
TaskWrapper(TaskWrapper const&);
TaskWrapper(TaskWrapper&&);
TaskWrapper& operator= (TaskWrapper const&);
TaskWrapper& operator= (TaskWrapper&&);
private:
Task* m_ptr; // preferably a unique_ptr
};
您也可以让TaskWrapper
衍生自Task
。
如果我正确理解了问题,请使用标准C 语法来访问tastimp,并根据需要致电Taskimpl成员实现。
您不能直接这样做,因为应用程序和DLL分别链接并且没有彼此的编译时间知识。该应用程序在编译时不知道TaskImpl,因此编译器不能从中衍生出来,也无法创建可能是来自应用程序和DLL的Funcitons组合的VTable。
您可以组成对象,即在Applimp中创建一个TaskIMP的实例,并将所有函数委派给Applimp内部的Taskimp实例。在许多情况下,这是不方便的。
一种更方便的方法是从DLL中导出TaskImpl的实现:将整个班级声明为__DLLEXPORT。不幸的是,这是达到最低的方法,在一个大型项目中,它可能会导致巨大的DLL导出部分,其中10000 C - 名称 - 刻录条目。但是您也许可以将taskimpl用作其他DLL或应用程序中的基类。
btw,这不会编译,因为applimp是从任务派生的,而任务*不能隐式地施放到applimpl。
applimp * anewtask = static_cast(newtask());