我正在尝试加载.dll文件中定义的类。但是,有两种在dll中定义类的方式略有不同。我不确定哪种方法更合法,我也不知道为什么第二种方法也行得通。这是一个简单的示例:
方法1:在main.cpp
:
#include <iostream>
#include <windows.h>
#include <memory>
#include "bar.h"
using namespace std;
typedef bar* (* MYDLLPROC)();
int main()
{
unique_ptr<bar> theresult;
auto thelib = LoadLibrary(TEXT("foo.dll"));
if (thelib != NULL) {
MYDLLPROC theprocs = (MYDLLPROC)GetProcAddress(thelib, "Myfoo");
cout << "load successfully" << endl;
theresult.reset(theprocs());
theresult->printmsg();
} else {
cout << "cannot load the dll" << endl;
}
return 1;
}
在中bar
被定义为纯虚拟类bar.h
:
class bar {
public:
virtual ~bar() {};
virtual void printmsg() = 0;
};
在foo.dll
源文件中:
#include <iostream>
#include <windows.h>
#include "bar.h"
using namespace std;
class foo: public bar {
public:
foo() { cout << "foo is instantiated" << endl; }
~foo() {}
void printmsg() final { cout << "msg from foo print" << endl; }
};
extern "C" __declspec(dllexport) foo* __cdecl Myfoo()
{
return new foo();
}
在第一种方法中,纯虚拟类bar
用作接口,并且它的成员函数被foo
dll加载时的成员函数覆盖是有意义的。
但是,我发现foo
不必继承自bar
,只要foo
有了Vtable ,一切仍然可以使用:
在第二种方法中,除以下内容的定义外,其他内容均相同foo
:
#include <iostream>
#include <windows.h>
using namespace std;
class foo {
public:
foo() { cout << "foo is instantiated" << endl; }
virtual ~foo() {}
virtual void printmsg() final { cout << "msg from foo print" << endl; }
};
extern "C" __declspec(dllexport) foo* __cdecl Myfoo()
{
return new foo();
}
谁能让我知道第二种方法为什么起作用?我有点困惑,因为foo
和bar
并没有关系,但是中的成员函数bar
仍然可以被覆盖。
因此,您将返回的函数转换为返回foo*
的函数bar*
,然后调用它。
最终结果是您有一个指向foo
不相关类型的指针bar
。以任何方式使用它都会导致不确定的行为。
printmsg
在两个特定的虚拟表中,虚函数的位置是相同的,因此在这种特定情况下似乎可以使用,因此bar::printmsg
在实例上foo
调用仅会调用“虚拟表中的第N个条目”。如果将另一个虚拟成员添加到foo
before printmsg
,则可能会调用它(否则该程序可能会崩溃)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句