How pure virtual functions mechanism in C ++ exposes functions from DLL
Consider the following C ++ code snippet
1. In EXE:
Base.hpp
#ifndef _BASE_H_
#define _BASE_H_
class Base
{
public:
Base(){};
virtual double Add(double &x, double &y) = 0;
};
#endif
main.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. In an implicitly linked DLL
Derived.hpp
#ifndef _DERIVED_H_
#define _DERIVED_H_
#include "Base.hpp"
class Derived : public Base
{
public:
double Add(double &x, double &y);
};
#endif
DerivedFactory.hpp
#ifndef _DERIVEDFACTORY_H_
#define _DERIVEDFACTORY_H_
#include "Derived.hpp"
class DerivedFactory
{
public:
__declspec(dllexport) static Derived* Create();
};
#endif
Derived.cpp
#include "Derived.hpp"
double Derived::Add(double &x, double &y)
{
return x + y;
}
DerivedFactory.cpp
#include "DerivedFactory.hpp"
Derived* DerivedFactory::Create()
{
Derived* theDerived = new Derived;
return theDerived;
}
-
The main question is, how does the exe "know" to decide the correct Add implementation from the dll when the only exported function is Create ()?
-
Why am I getting a linker error when Add () is "just" virtual and not pure virtual?
source to share
-
The DLL will contain a vtable
Derived
somewhere in the global data section. InstancesDerived
created in the DLL will have their vtable assigned to this address. -
If the
Base
ad isAdd()
not purely virtual, you must provide a definition for it above the ad.
Change: . For an explanation of what a vtable is, see this answer: Why do I need a virtual table?
From a purely stylistic point of view, I would also mention that in this type of situation, the factory usually returns instances of the class Base
, for example:
DerivedFactory.hpp
#include "Base.hpp"
class DerivedFactory
{
public:
__declspec(dllexport) static Base* Create();
};
This way, the encapsulation Derived
remains completely and neatly in the DLL.
source to share
The virtual table in Derived is set by the DLL when instantiated, so when the methods are called through the Base pointer, the virtual table will already have the correct addresses set in the virtual table (EXE will use the Derived virtual table from the DLL).
Note that the EXE does not import the virtual table from the DLL when linking, because it does not need it (it accesses the DLL virtual table obtained in memory via the Base interface). So it works not only with implicit linking, but when the DLL is loaded at runtime (LoadLibrary / GetProcAddress), but for that, the factory method is best not part of a factory class, but a standalone external exported function "C").
More on pure virtual interfaces and DLLs: Providing an SDK for my C ++ application
source to share