Search code examples
c++pointerspolymorphismcontainersvtable

How to enforce parent / derived relationship of two independent classes inside a container?


Consider the following class definitions:

#include <string>

class CParty
{
public:
    CParty();
    virtual ~CParty();
    int m_nId;
};

class CPartyEx : public CParty
{
public:
    CPartyEx();
    ~CPartyEx();
    std::string m_sName;
};

class CTransaction
{
public:
    CTransaction();
    virtual ~CTransaction();
    int m_nClassNo;
};

class CTransactionEx : public CTransaction
{
public:
    CTransactionEx();
    ~CTransactionEx();
    std::string m_sDesc;
};

class CObject
{
public:
    CObject();
    ~CObject();
    CParty* m_pParent;
    CTransaction* m_pTransaction;
};

In an appropriate implementation, I would like to create the following types of CObject storage objects:

// OK: Basic party with basic transaction
CObject iObject1;
iObject1.m_pParent = new CParty();
iObject1.m_pTransaction = new CTransaction();

// OK: Extended party with extended transaction
CObject iObject2;
iObject2.m_pParent = new CPartyEx();
iObject2.m_pTransaction = new CTransactionEx();

However, the current CObject definition does not prevent mixing CParty and CTransaction types which are incompatible with one another:

// Not intended: Basic party with extended transaction
CObject iObject3;
iObject3.m_pParent = new CParty();
iObject3.m_pTransaction = new CTransactionEx();

// Not intended: Extended party with basic transaction
CObject iObject4;
iObject4.m_pParent = new CPartyEx();
iObject4.m_pTransaction = new CTransaction();

Is it somehow possible to place a restriction on how the two objects can be linked together inside a CObject instance?


Solution

  • You could encapsulate the decision in the CObject constructor:

    class CObject
    {
    public:
        CObject(bool extended = false);
    };
    
    CObject::CObject (bool extended)
    {
        if (extended)
        {
            m_pParent = new CPartyEx();
            m_pTransaction = new CTransactionEx();
        }
        else
        {
            m_pParent = new CParty();
            m_pTransaction = new CTransaction();
        }
    }