您的位置:首页 > 其它

用类模板做的智能指针

2015-12-26 13:38 239 查看

前言

做一个类模板的准备工作.

先准备一个普通类, 她的关联类都调试过.

将准备改到类模板的类声明为template<typename T>, 一个类模板放在一个.h中

加入关联类的前向声明

在类模板中加入友元类模板的声明

为了维护方便, 将所有类实现都内联实现. 不要再放到类外部, 防止该类模板进行类特例时, 看的眼花~

测试代码

// SmartPtrD.cpp : Defines the entry point for the console application.
// * 运用智能指针改写MyString

#include "stdafx.h"
#include "MyString.h"
#include "SmartPtr.h"

void fnTestTemplateSmartPtr();
void fnTestOnlyMyString();

int main(int argc, char* argv[])
{
    // fnTestOnlyMyString();
    fnTestTemplateSmartPtr();
    /** run result
    ISmartPtrElement::ISmartPtrElement()00333CA8, m_pOwner = 00333C50
    CSmartPtr::CSmartPtr()0018FED8, m_pPtr = 00333CA8
    ISmartPtrElement::ISmartPtrElement()00333E40, m_pOwner = 00333F18
    CSmartPtr::CSmartPtr()0018FED0, m_pPtr = 00333E40
    ISmartPtrElement::~ISmartPtrElement()00333CA8
    inline CSmartPtr& operator = (const CSmartPtr& obj)0018FED8, m_pPtr = 00333E40
    CMyString::fnTest
    CMyString::fnTest
    CMyString::fnTest
    CMyString::fnTest
    ptr     = 0x00333F18
    ptr + 1 = 0x00333F28
    CSmartPtr::~CSmartPtr()0018FED0, m_pPtr = 00333E40
    CSmartPtr::~CSmartPtr()0018FED8, m_pPtr = 00333E40
    ISmartPtrElement::~ISmartPtrElement()00333E40
    */

	cout << "END, press any key to quit" << endl;
    _getch();
	return 0;
}

void fnTestTemplateSmartPtr()
{
    CMyString* pMyString = new CMyString;
    CMyString** ppMyString = NULL;
    _ASSERT(NULL != pMyString);
    CSmartPtr<CMyString> ptr = pMyString;
    CSmartPtr<CMyString> ptr2 = new CMyString;
    size_t nSize = sizeof(CMyString);
    
    typedef union un_tmp
    {
        size_t nAddr;
        CMyString* pClass;
    }UN_TMP;
    UN_TMP addr;
    
    /// 模拟指针操作 =
    ptr = ptr2;
    
    /// 模拟指针操作 ->
    ptr->fnTest();
    
    /// 模拟指针操作 *
    (*ptr).fnTest();
    
    /// 模拟指针操作 &
    ppMyString = &ptr;
    (*ppMyString)->fnTest();
    (*(&ptr))->fnTest();
    
    /// 打印智能指针中存储的对象指针之值
    addr.pClass = *(&ptr);
    cout << "ptr     = 0x"
        << std::hex << setiosflags(ios::uppercase) << setfill('0') << setw(8) 
        << addr.nAddr << endl;
    
    /// 模拟指针操作 +
    addr.pClass = ptr + 1; ///< 只是计算地址, 不会报错^_^
    cout << "ptr + 1 = 0x" 
        << std::hex << setiosflags(ios::uppercase) << setfill('0') << setw(8) 
        << addr.nAddr << endl;
}

void fnTestOnlyMyString()
{
    CMyString* pstr1 = new CMyString("Hello");
    
    SAFE_DELETE(pstr1);
}


common.h

/// @file common.h
/// @brief 公用头文件

#ifndef COMMON_H_1460AB26_69BA_45E7_8E75_3867BF8DA316
#define COMMON_H_1460AB26_69BA_45E7_8E75_3867BF8DA316

#include <iostream>
#include <limits>
#include <string>

#include <crtdbg.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>
#include <conio.h>
#include <iomanip>

using namespace std;

#ifndef BOOL
#define BOOL int
#define TRUE 1
#define FALSE 0
#endif // #ifndef BOOL

#ifndef NULL
#define NULL 0
#endif // #ifndef NULL

#ifndef SAFE_DELETE
#define SAFE_DELETE(x) \
{ \
    if (NULL != (x)) \
    { \
        delete (x); \
        (x) = NULL; \
    } \
}
#endif // #ifndef SAFE_DELETE

#ifndef SAFE_DELETE_ARY
#define SAFE_DELETE_ARY(x) \
{ \
    if (NULL != (x)) \
    { \
        delete[] (x); \
        (x) = NULL; \
    } \
}
#endif // #ifndef SAFE_DELETE_ARY

#endif // #ifndef COMMON_H_1460AB26_69BA_45E7_8E75_3867BF8DA316


ISmartPtrElement.h

// ISmartPtrElement.h: interface for the ISmartPtrElement class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_ISMARTPTRELEMENT_H__55DFBE74_2052_48E8_9CD6_9FD1567E61C3__INCLUDED_)
#define AFX_ISMARTPTRELEMENT_H__55DFBE74_2052_48E8_9CD6_9FD1567E61C3__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "common.h"
#include "MyString.h"
#include "SmartPtr.h"

/// ----------------------------------------
/// >> class ISmartPtrElement 普通实现
/// ----------------------------------------

/// 模板类的前向声明
template<typename T>
class CSmartPtr;

/// 抽象类, CSmartPtr中操作的元素类型
template<typename T>
class ISmartPtrElement  
{
    friend class CSmartPtr<T>; ///< 声明另外一个模板类为友元
    
public:
    ISmartPtrElement(T* pOwner)
        :m_iRefCount(0)
        ,m_pOwner(NULL)
    {
        _ASSERT(NULL != pOwner);
        m_pOwner = pOwner;
        cout << "ISmartPtrElement::ISmartPtrElement()" 
            << std::hex << setiosflags(ios::uppercase) << setfill('0') << setw(8)
            << (size_t)this 
            
            << ", m_pOwner = " 
            << std::hex << setiosflags(ios::uppercase) << setfill('0') << setw(8)
            << (size_t)m_pOwner 
            << endl;
    }

    virtual ~ISmartPtrElement()
    {
        cout << "ISmartPtrElement::~ISmartPtrElement()" 
            << std::hex << setiosflags(ios::uppercase) << setfill('0') << setw(8)
            << (size_t)this 
            << endl;
    }
    
    void AddRef() {m_iRefCount++;}
    int Release()
    {
        if (m_iRefCount <= 0)
        {
            return 0;
        }
        
        if (--m_iRefCount == 0)
        {
            SAFE_DELETE(m_pOwner);
        }
        
        return m_iRefCount;
    }

private:
    int m_iRefCount; ///< 参考计数
    T* m_pOwner; ///< 所有者
};

/// ----------------------------------------
/// << class ISmartPtrElement 普通实现
/// ----------------------------------------

#endif // !defined(AFX_ISMARTPTRELEMENT_H__55DFBE74_2052_48E8_9CD6_9FD1567E61C3__INCLUDED_)


MyString.h

// MyString.h: interface for the CMyString class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_MYSTRING_H__3946972C_1380_4373_91E6_0C3BFDFEEED6__INCLUDED_)
#define AFX_MYSTRING_H__3946972C_1380_4373_91E6_0C3BFDFEEED6__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "common.h"

class CMyString  
{
    /// 构造函数, 析构函数, 拷贝构造函数
public:
    CMyString();
    CMyString(const char* psrc);
    virtual ~CMyString();
    
    CMyString(CMyString& src);
    CMyString(CMyString* psrc);
    
    /// 转换运算符重载
    
    /// 运算符重载
    void operator = (const char* pSrc);
    CMyString operator + (const char* pSrc);
    CMyString& operator += (const char* pSrc);
    bool operator > (const char* pSrc);
    bool operator >= (const char* pSrc);
    bool operator < (const char* pSrc);
    bool operator <= (const char* pSrc);
    bool operator == (const char* pSrc);
    bool operator != (const char* pSrc);
    const char* operator [] (size_t nIndex) const;
    
    /// 成员方法
    const char* c_str() const;
    const char* StringFormatV(char* szFormat, ...);

    /// 测试用的方法, 就是为了打印点东西, 刷存在感
    void fnTest()
    {
        cout << "CMyString::fnTest" << endl;
    }
    
private:
    virtual CMyString* strcat(const char* pSrc);
    void setString(const char* pSrc);
    CMyString* strcpy(const char* pSrc);
    int compare(const char* pSrc);
    
    void init();
    void uninit();
    
    // member data
private:
    char* m_lpString; ///< 开辟(new)的字符串缓冲区
    int   m_nLen; ///< 字符串长度
    
    /// 如果最终要操作的字符串比缓冲区小, 就不用另外再开辟缓冲区了
    int   m_nSpaceLen; ///< 缓冲区总长度
};

ostream& operator<< (ostream& cout, CMyString& right);

#endif // !defined(AFX_MYSTRING_H__3946972C_1380_4373_91E6_0C3BFDFEEED6__INCLUDED_)


SmartPtr.h

// SmartPtr.h: interface for the CSmartPtr class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_SMARTPTR_H__99AE9DED_C11E_47ED_927E_E7A058B8E9FC__INCLUDED_)
#define AFX_SMARTPTR_H__99AE9DED_C11E_47ED_927E_E7A058B8E9FC__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "common.h"
#include "ISmartPtrElement.h"

///----------------------------------------
/// >> class CSmartPtr 普通实现
///----------------------------------------

/// 模板类的前向声明
template<typename T>
class ISmartPtrElement;

template<typename T>
class CSmartPtr
{
public:
    CSmartPtr(T * pElement)
        :m_pPtr(NULL)
    {
        if (NULL != pElement)
        {
            m_pPtr = new ISmartPtrElement<T>(pElement);
            _ASSERT(NULL != m_pPtr);
            m_pPtr->AddRef();
        }
        
        cout << "CSmartPtr::CSmartPtr()" 
            << std::hex << setiosflags(ios::uppercase) << setfill('0') << setw(8)
            << (int)this 
            
            << ", m_pPtr = " 
            << std::hex << setiosflags(ios::uppercase) << setfill('0') << setw(8)
            << (int)m_pPtr
            << endl;
    }

    virtual ~CSmartPtr()
    {
        cout << "CSmartPtr::~CSmartPtr()" 
            << std::hex << setiosflags(ios::uppercase) << setfill('0') << setw(8)
            << (int)this 
            
            << ", m_pPtr = " 
            << std::hex << setiosflags(ios::uppercase) << setfill('0') << setw(8)
            << (int)m_pPtr
            << endl;
        
        if (NULL != m_pPtr)
        {
            if (0 == m_pPtr->Release())
            {
                SAFE_DELETE(m_pPtr);
            }
        }
    }
    
    /// 运算符重载 
    
    /// 重载常用的指针操作
    inline CSmartPtr& operator = (const CSmartPtr& obj)
    {
        if (m_pPtr == obj.m_pPtr)
        {
            return *this;
        }
        
        if (NULL != m_pPtr)
        {
            if (0 == m_pPtr->Release())
            {
                SAFE_DELETE(m_pPtr);
            }
        }
        
        m_pPtr = obj.m_pPtr;
        if (NULL != m_pPtr)
        {
            cout << "inline CSmartPtr& operator = (const CSmartPtr& obj)" 
                << std::hex << setiosflags(ios::uppercase) << setfill('0') << setw(8)
                << (int)this 
                
                << ", m_pPtr = " 
                << std::hex << setiosflags(ios::uppercase) << setfill('0') << setw(8)
                << (int)m_pPtr
                << endl;
            
            m_pPtr->AddRef();
        }
        
        return *this;
    }
    
    inline T* operator ->()
    {
        return m_pPtr->m_pOwner;
    }
    
    inline T operator *()
    {
        return *m_pPtr->m_pOwner;
    }
    
    inline T** operator &()
    {
        return &m_pPtr->m_pOwner;
    }
    
    inline T* operator +(size_t nOffset)
    {
        return (m_pPtr->m_pOwner + nOffset);
    }
    
private:
    ISmartPtrElement<T>* m_pPtr;
};

///----------------------------------------
/// << class CSmartPtr 普通实现
///----------------------------------------

#endif // !defined(AFX_SMARTPTR_H__99AE9DED_C11E_47ED_927E_E7A058B8E9FC__INCLUDED_)


MyString.cpp

// MyString.cpp: implementation of the CMyString class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "MyString.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CMyString::CMyString()
{
    init();
}

CMyString::~CMyString()
{
    uninit();
}

CMyString::CMyString(CMyString& src)
{
    init();
    this->strcpy(src.c_str());
}

CMyString::CMyString(CMyString* psrc)
{
    init();

    if (NULL != psrc)
    {
        this->strcpy(psrc->c_str());
    }
}

CMyString::CMyString(const char* psrc)
{
    init();

    if (NULL != psrc)
    {
        this->strcpy(psrc);
    }
}

void CMyString::operator = (const char* pSrc)
{
    strcpy(pSrc);
}

CMyString CMyString::operator + (const char* pSrc)
{
    CMyString tmp;

    tmp = *this;
    tmp += pSrc;
    return tmp;
}

CMyString& CMyString::operator += (const char* pSrc)
{
    strcat(pSrc);
    return *this;
}

const char* CMyString::operator [] (size_t nIndex) const
{
    char* pRc = "";

    if ((NULL != m_lpString) 
        && (nIndex >= 0) 
        && (nIndex < strlen(m_lpString)))
    {
        pRc = m_lpString + nIndex;
    }

    return pRc;
}

int CMyString::compare(const char* pSrc)
{
    int iRc = 0;
    const char * pMe = (NULL != m_lpString) ? m_lpString : "";
    const char * pSrcCpy = (NULL != pSrc) ? pSrc : "";
    
    /// strcmp入参为空指针会报错
    iRc = ::strcmp(pMe, pSrcCpy);

    return iRc;
}

bool CMyString::operator > (const char* pSrc)
{
    return (compare(pSrc) > 0);
}

bool CMyString::operator >= (const char* pSrc)
{
    return (compare(pSrc) >= 0);
}

bool CMyString::operator < (const char* pSrc)
{
    return (compare(pSrc) < 0);
}

bool CMyString::operator <= (const char* pSrc)
{
    return (compare(pSrc) <= 0);
}

bool CMyString::operator == (const char* pSrc)
{
    return (compare(pSrc) == 0);
}

bool CMyString::operator != (const char* pSrc)
{
    return (compare(pSrc) != 0);
}

void CMyString::init()
{
    m_lpString = NULL;
    m_nLen = 0;
    m_nSpaceLen = 0;
}

void CMyString::uninit()
{
    SAFE_DELETE_ARY(m_lpString);
    m_nLen = 0;
    m_nSpaceLen = 0;
}

void CMyString::setString(const char* pSrc)
{
    this->strcpy(pSrc);
}

const char* CMyString::c_str() const
{
    if (NULL == m_lpString)
    {
        return "";
    }
    else
    {
        return m_lpString;
    }
}

CMyString* CMyString::strcpy(const char* pSrc)
{
    int iLenNew = 0;
    char* pNewString = NULL;
    if (NULL == pSrc)
    {
        return this;
    }
    
    iLenNew = ::strlen(pSrc);
    if (iLenNew > (m_nSpaceLen - 1))
    {
        pNewString = new char[iLenNew + 1];
        _ASSERT(NULL != pNewString);

        pNewString[0] = '\0';
        ::strcpy(pNewString, pSrc);
        SAFE_DELETE_ARY(m_lpString);
        
        m_nLen = iLenNew;
        m_nSpaceLen = m_nLen + 1;
        m_lpString = pNewString;
    }
    else
    {
        m_nLen = strlen(pSrc);
        _ASSERT(NULL != m_lpString);

        if (0 != ::strcmp(m_lpString, pSrc))
        {
            ::strcpy(m_lpString, pSrc);
        }
    }

    return this;
}

CMyString* CMyString::strcat(const char* pSrc)
{
    int iLenNew = 0;
    char* pNewString = NULL;
    if (NULL == pSrc)
    {
        return this;
    }

    if (NULL == m_lpString)
    {
        this->strcpy(pSrc);
        return this;
    }

    iLenNew = m_nLen + strlen(pSrc);
    if (iLenNew > (m_nSpaceLen - 1))
    {
        pNewString = new char[iLenNew + 1];
        pNewString[0] = '\0';
        ::strcpy(pNewString, m_lpString);
        SAFE_DELETE_ARY(m_lpString);
        ::strcat(pNewString, pSrc);

        m_nLen = iLenNew;
        m_nSpaceLen = m_nLen + 1;
        m_lpString = pNewString;
    }
    else
    {
        m_nLen += strlen(pSrc);
        ::strcat(m_lpString, pSrc);
    }

    return this;
}

const char* CMyString::StringFormatV(char* szFormat, ...)
{
    size_t nStrLen = 1024 * 100; ///< 默认开100K空间
    va_list args;
    char* pNewString = NULL;
    
    va_start(args, szFormat);
    
    /**
    _MSC_VER Defines the compiler version. 
    Defined as 1200 for Microsoft Visual C++ 6.0. Always defined. 
    */
    if (_MSC_VER > 1200)
    {
        /// vs6不允许这么用, vs2010可以
        /// 估算需要的缓冲区长度
        nStrLen = _vsnprintf(NULL, 0, szFormat, args);
    }
    
    pNewString = new char[nStrLen + 1];
    _ASSERT(pNewString);
    ::memset(pNewString, 0, (nStrLen + 1) * sizeof(char));
    
    nStrLen = _vsnprintf(pNewString, nStrLen, szFormat, args);
    va_end(args);

    this->strcpy(pNewString);
    return this->c_str();
}

ostream& operator<< (ostream& cout, CMyString& right)
{
    cout << right.c_str();
    return cout;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: