C++ 中的纯虚函数机制如何公开来自 DLL 的函数
How does pure virtual functions mechanism in c++ exposes functions from DLL
考虑下一个 c++ 代码片段
1. 在 EXE 中:
Base.hpp
#ifndef _BASE_H_
#define _BASE_H_
class Base
{
public:
Base(){};
virtual double Add(double &x, double &y) = 0;
};
#endif
主.cpp
#include <iostream>
#include "Base.hpp"
#include "DerivedFactory.hpp"
void main()
{
Base *theBase = DerivedFactory::Create();
double x = 4.9, y = 3.3,z;
z = theBase->Add(x, y);//Works when Add is pure virtual function, but how???
//Linker error when Add is not pure virtual
}
2. 在隐式链接的 DLL 中
衍生.hpp
#ifndef _DERIVED_H_
#define _DERIVED_H_
#include "Base.hpp"
class Derived : public Base
{
public:
double Add(double &x, double &y);
};
#endif
衍生工厂.hpp
#ifndef _DERIVEDFACTORY_H_
#define _DERIVEDFACTORY_H_
#include "Derived.hpp"
class DerivedFactory
{
public:
__declspec(dllexport) static Derived* Create();
};
#endif
派生.cpp
#include "Derived.hpp"
double Derived::Add(double &x, double &y)
{
return x + y;
}
衍生工厂.cpp
#include "DerivedFactory.hpp"
Derived* DerivedFactory::Create()
{
Derived* theDerived = new Derived;
return theDerived;
}
主要问题是,当唯一从 dll 导出的函数是 Create(( 时,exe 如何"知道"解决从 dll 添加的正确实现?
为什么当 Add(( 是"只是"虚拟而不是纯虚拟时出现链接器错误?
-
DLL 将在其全局数据部分的某个位置包含
Derived
的 vtable。在 DLL 中创建的Derived
实例的 vtable 指针将分配给该地址。 -
如果
Base
的Add()
声明不是纯虚拟的,则必须在声明之上为其提供定义。
编辑:有关vtable是什么的解释,请参阅此答案: 为什么需要虚拟表?
从纯粹的风格角度来看,我还要提到,在这种情况下,工厂通常会返回Base
类的实例,如下所示:
衍生工厂.hpp
#include "Base.hpp"
class DerivedFactory
{
public:
__declspec(dllexport) static Base* Create();
};
这样,Derived
的封装将完全整齐地保留在 DLL 中。
派生中的虚拟表由 DLL 在创建实例时设置,因此当通过 Base 指针调用方法时,虚拟表将已经在虚拟表中设置了正确的地址(EXE 将使用来自 DLL 的派生虚拟表(。
请注意,EXE 在链接时不会从 DLL 导入虚拟表,因为它不需要(它通过 Base 接口访问 DLL 派生在内存中的虚拟表(。因此,它不仅适用于隐式链接,而且适用于在运行时加载 DLL 时(LoadLibrary/GetProcAddress - 但为此,工厂方法最好不是工厂类的一部分,而是独立的外部"C"导出函数(。
有关纯虚拟接口和 DLL 的更多详细信息,另请参阅此处:为我的 C++ 应用程序提供 SDK
相关文章:
- 函数何时会在c++中包含stack_Unwind_Resume调用
- A类的定义需要B类的定义,如何在不公开B的定义的情况下公开A的公共函数?
- 无法使函数公开。获取:"LNK2005"错误。如何调试链接器错误
- 在父类中公开受保护的构造函数
- 标准对此指向成员函数类型模板参数有何说明?是我的代码有误,还是 MSVS 16.6 有问题?
- 为什么继承的受保护构造函数不能公开?
- 使用 Rcpp 公开将指向对象的指针作为参数的构造函数
- 如何将 cpp 文件中的静态函数公开给其他文件
- "virtual"对C++析构函数有何影响?
- 在完美转发函数中公开参数类型,避免代码重复
- C++ 中的纯虚函数机制如何公开来自 DLL 的函数
- C++ 友元函数在内存位置上有何不同?
- C/C++ 函数/方法与 Java 的公开
- 在 qml 中公开基类函数
- 如何创建公开泛型函数的 DLL
- 如何为想要公开相互递归函数的仅标头库组织包含
- 授予对另一个类的函数访问,而无需公开它
- 如果基类是公开继承的,那么基类的公共静态函数是否会成为派生类的成员函数
- 指向成员函数的指针与指向数据成员的指针有何不同
- 使用 boost::p ython 将虚拟成员函数从 C++ 公开到 Python