简体   繁体   中英

C++ pimpl idiom and exporting data structure

I implemented the pimpl pattern to hide the implementation in my dll from the rest of the world but I'm stuck on how to hide a struct that needs to be exported out of the dll. Below is a simple representation of my problem (left out some parts).

idcom.h

class IDcom_impl;

class IDcom
{
public:
    IDcom_API IDcom();
    void IDcom_API createList();

private:
    std::unique_ptr< IDcom_impl > m_impl;
}

idcom.cpp

IDcom::IDcom() :
    m_impl( new IDcom_impl())
{}

void IDcom::createList()
{
   m_impl->createList();
}

idcom_impl.h

class IDcom_impl
{
public:
    struct IDcom_API ListItem
    {
       std::string var1;
       std::string var2;
    }

    IDcom_impl(){}

    void createList();

    std::vector< ListItem > m_list;
}

If I want to expand ListItem with another variable std::string var3 and not break the ABI and get a list of "listitem"s out of the dll, what are my options? I know that in order for the application to know something about the "ListItem" this struct has to be exported but is that enough and is this a good design

Problem here is auto generated destructor. To benefit from forward declarations it should go like this:

#include <memory>

class IDcom_impl;

class IDcom
{
public:
    IDcom_API ~IDcom();
    IDcom_API IDcom();

    void IDcom_API createList();

private:
    std::unique_ptr< IDcom_impl > m_impl;
};

idcom.cpp

#include "idcom_impl.h"
#include "idcom.h"

IDcom::~IDcom() = default;

IDcom::IDcom() :
    m_impl( new IDcom_impl())
{}

void IDcom::createList()
{
   m_impl->createList();
}

Note if you do not declare destructor compiler will try to auto generate it in every translation unit where destruction can happen. To be able generate destructor compiler have to know how to destroy field m_impl and this means he have to know destructor of IDcom_impl .

As a result advantages of pimpl pattern is getting busted.

If you declare destructor it will be associated with specific translation unit which have required knowledge about IDcom_impl and no other translation unit has to now anything about IDcom_impl .

I think I have it but I need to run this by you guys to make sure that I have a good design. So basically the pimpl is implemented correctly but the problem is the data structure expansion ( say adding a new member variable say var3 in original post ) that I have in the dll and should be shared with the application AND a new version of the dll ( say v2 ) should work with the current version of the app ( say v2 ) and the previous one ( say v1 ) so without recompiling the app ( hence compatibility with v1 ). I have posted only the necessary ( makes reading easier :-) ) , the code compiles, runs and works but is this a good design for the requirements stated above and in my original post.

idcom_global.h :

#if defined( IDCOM_LIBRARY )
 #define IDCOMDLL_API  __declspec( dllexport )
#else
 #define IDCOMDLL_API  __declspec( dllimport )
#endif

idcom.h :

#include "idcom_listitem.h"

class idcomImpl;

class  idcom
{
public:
    IDCOMDLL_API idcom();
    IDCOMDLL_API ~idcom();
    bool IDCOMDLL_API retrieveList( std::vector< ListItem >& list );

private:
    std::unique_ptr< idcomImpl > m_impl;
};

idcom.cpp :

idcom::idcom() :
    m_impl( new idcomImpl())
{}

idcom::~idcom() = default;

bool idcom::retrieveList( std::vector< ListItem >& list )
{
    return m_impl->retrieveList( list );
}

idcomimpl.h :

class idcomImpl
{
public:
    idcomImpl(){};
    ~idcomImpl(){};
    bool retrieveList( std::vector< ListItem >& worklist );
};

idcomimpl.cpp :

bool idcomImpl::retrieveList( std::vector< ListItem >& worklist )
{
....//implementation here
}

idcom_listitem.h:

struct IDCOMDLL_API ListItem
{
    std::string id;
    std::string lastname;
    std::string firstname;
    std::string prefix;

    //expansion of members here in the future e.g. std::string dateOfBirth;
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM