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?

+3


source to share


2 answers


  • The DLL will contain a vtable Derived

    somewhere in the global data section. Instances Derived

    created in the DLL will have their vtable assigned to this address.

  • If the Base

    ad is Add()

    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.

+3


source


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

+2


source







All Articles