Use the handle class to encapsulate the inheritance system

Source: Internet
Author: User

In DLL encapsulation, interface classes are generally used, that is, pure virtual classes, to achieve the purpose of separating interfaces from implementations. However, the encapsulated class can only be used indirectly by returning pointers or references. Compared with this, handle class is a good alternative. Except for the name, the usage of the handle class is basically the same as that of the encapsulated class. The ease of use of the handle class is based on a certain amount of operational efficiency (of course, the interface class also consumes a certain amount of operational efficiency). Therefore, it is generally used when the operational efficiency requirement is not high. In addition, because the handle class has more encoding than the interface class, it is generally used to encapsulate classes with relatively small changes. In an appropriate scenario, using the handle class is a good choice, and it can also be used to encapsulate the inheritance system. The following is an example of using the handle class to encapsulate the inheritance system.

There is an inheritance system. The parent class is cbase and the Child class is cderived. Their corresponding handle classes are hbase and hderived, and hbase and hderived are also inherited, as shown below:

#ifndef __CLASS_BASE_H__
#define __CLASS_BASE_H__

class CBase
{
public:
CBase(void);
virtual ~CBase(void);

public:
int GetData(void);
virtual void SetData(int nData);

private:
int m_nData;
};

#endif

 

#ifndef __CLASS_DERIVED_H__
#define __CLASS_DERIVED_H__

#include "Base.h"

class CDerived : public CBase
{
public:
CDerived(void);
virtual ~CDerived(void);

public:
virtual void SetData(int nData);
virtual void SetString(const char* pszString);
};

#endif

 

Use the smart pointer STD: auto_ptr in hbase to manage the cbase object pointer. Here, copying and assigning values of the handle object is temporarily prohibited. If necessary, you can use a smart pointer with the count function for Management. The cbase object is released only when the last handle object is parsed.

#ifndef __HANDLE_BASE_H__
#define __HANDLE_BASE_H__

#include <memory>

class CBase;

class HBase
{
public:
HBase(void);
virtual ~HBase(void);

protected:
HBase(CBase* pBase);
CBase* GetImpl(void);

private:
HBase(HBase& rhs);
HBase& operator =(HBase& rhs);

public:
int GetData(void);
virtual void SetData(int nData);

private:
std::auto_ptr<CBase> m_apImpl;
};

#endif

Hbase constructor:

HBase::HBase(void)
: m_apImpl(new CBase)
{

}

HBase::HBase(CBase* pBase)
: m_apImpl(pBase)
{

}

 

The default constructor is used when no subclass is available. The object with the cbase Object Pointer parameter is called when the subclass is constructed. The getimpl function is provided to the subclass to obtain the cbase object pointer.

CBase* HBase::GetImpl(void)
{
return m_apImpl.get();
}

Next, let's take a look at hderived:

# Ifndef _ handle_derived_h __
# DEFINE _ handle_derived_h __

# Include <memory>
# Include "hbase. H"

Class cderived;

Class hderived: Public hbase
{
Public:
Hderived (void );
Virtual ~ Hderived (void );

PRIVATE:
Hderived (hderived & RHs );
Hderived & operator = (hderived & RHs );

Public:
Virtual void setdata (INT ndata );


PRIVATE:
Cderived * const m_pimpl; // values cannot be assigned except the constructor.
};

# Endif

M_pimpl is decorated with const so that it holds the pointer to the cderived object during the construction, but cannot be assigned again later to avoid unintentional changes. The pointer of the cderived object is first passed to hbase: m_apimpl management, and m_pimpl is simply held.

HDerived::HDerived(void)
: HBase(new CDerived)
, m_pImpl(static_cast<CDerived*>(HBase::GetImpl()))
{

}

In this way, when the subclass handle is destructed, The cderived Object Pointer is parsed only at the parent class level.

Implementation of hbase's cbase encapsulation:

int HBase::GetData(void)
{
return m_apImpl->GetData();
}


void HBase::SetData(int nData)
{
m_apImpl->SetData(nData);
}

In this way, the member function call polymorphism can be implemented, but there is a defect that it cannot be called like objderived. cbase: setdata.

 

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.