30_友元和引用计数

作业讲解

1.只能产生一个对象(单例模式),构造私有了编译器报错。类里面私有提供一个静态对象,类里面公有静态方法产生一个对象,返回静态对象。解决了资源浪费

Class A

{

Public:

Static A* getInstance()
{

       Return theObj;

}

Private:

        A()

        {

}

~A

{

}

Static A theObj;

}

A A::theObj;

2.只能在堆上产生对象,直接把析构设为私有,提供一个自杀函数

Class B

{

Public:

B() {};

 Void kill() {delete this};

Private:

~B() {};

}

3.只能在栈上创建对象

通过第一个控制创建的对象,自杀的方法,控制次数

4.设计,注重用户体验

 

友元

关键字

Friend

作用

1.破坏封装性的语法

Class Object

{

Public:

Object();

~Object();

Friend int main();   //main函数是我的朋友,友元全局函数

Private:

Void fun1() {};

Int m_iData;

}

 

Int main()
{

Object obj;

//obj.m_iData = 3; //如果加上frined就可以访问

//obj.fun1();

}

 

  1. 友元成员函数,在函数前加friend

声明实现分开写

  1. 友元类

当朋友的类声明一下

  1. 友元声明不分公有私有

引用计数设计

作用

  1. 浅拷贝的内存释放的问题,如果实际软件只能单开,用单例模式设计
  2. 如果多开的话每次开辟空间,增加计数器数据成员指针,不同的拷贝不一样的引用计数
  3. 如果想修改数据时不影响别的,使用写时拷贝(相当于深拷贝)

作业

为string类设计写时拷贝引用计数,使用string类的字符串缓冲区在多个对象中只存在一份拷贝

 //CMyString.h
#pragma once
#include 
#include 

using namespace std;

class CMyString
{
public:
    CMyString();    //无参构造
    CMyString(const char *str); //有参构造
    CMyString(CMyString& str);   //拷贝构造
    ~CMyString();   //析构
    unsigned getLength() const; //获取实际使用长度
    CMyString& myStrcpy(CMyString& str);    //拷贝字符串
    CMyString& myStrcat(CMyString& str);    //拼接字符串
    CMyString& myStrUpper();    //转换为大写
    CMyString& myStrLower();    //转换为小写
    const char *myFindSubStr(CMyString& str);    //查找子串-反向
    void myStrClear();  //清空
    const char *getBuff();  //获取字符串内存
    const char *getSubStrPointer(CMyString& str);   //查找位置 反向查找
    const int myStrcmp(CMyString& str);   //比较字符串
    const bool checkIsPlalindrome();    //检测是否为回文
    CMyString& myInsertStr(unsigned num, CMyString str);//指定位置插入字符串
    CMyString& myDeleteSubStr(CMyString str);//删除子串
    CMyString& myAlterChar(unsigned num, char ch);    //替换字符
    CMyString& myAlterStr(unsigned num, char ch);    //替换字符串
    CMyString& mySplitStr();//字符串分割 hello | world | test
    static string ValueOf(bool b);  //true ==> "true"
    static string ValueOf(char c);     //a ==> "a" 
    static string ValueOf(double d);   //3.5 ==>   "3.5" 
    static string ValueOf(float f);    //4.5f ==> "4.5" 
    static string ValueOf(int i);     //123 ==> "123" 
    static string ValueOf(long i);    //123 ==> "123" 
    static string ValueOf(short i);    //123 ==> "123" 
    static string ValueOf(const char* data); //char[] = "123" ==> string "123" 
    static string CopyValueOf(const char* data, int offset, int count); //char[] = "123" ==> string "123" 
    static string Format(CMyString format, ...);  //("%d", 123) ==> string "123" 
private:
    char*& getStr(); //获取字符串
    unsigned getSize() const; //获取实际占用大小
    void setStr(const char *str);  //设置字符串
    void setLength(const unsigned length); //设置实际占用长度
    void setSize(const unsigned size); //设置实际占用空间大小
    bool getIsNull() const;   //检查是否为空
    void setIsNull(bool b);   //设置是否为空
    void initString(const char *str = nullptr); //初始化字符串
    static void clearFormatHeap(); //清理格式化的堆空间
    void initRefCout();    //初始化引用计数次数
    void setRefCout(const int cout);  //修改引用计数的次数
    int getRefCout();   //获取引用计数次数
    int* getRefAddr();  //获取引用计数地址
    void refCoutAdd();  //引用计数次数增加
    void refCoutDel();  //引用计数次数减少
    void clearRefAddr();    //清空引用计数地址
private:
    char *m_pStr; //指向字符串的数组
    unsigned m_uLenth;   //字符串的实际使用长度
    unsigned m_uSize;    //字符串的实际占用的内存大小
    bool m_bIsNull; //是否为空标记
    static char *m_pFormatStr;  //临时格式化缓冲区
    int *m_pRefCout;    //引用次数指针
};
 //CMyString.cpp
#include "CMyString.h"


CMyString::CMyString()
{
    initString();
    initRefCout();
}

CMyString::CMyString(CMyString& str)
{
    if (str.getIsNull())
    {
        setIsNull(true);
        setLength(0U);
        setSize(0U);
    }
    else
    {
        setIsNull(false);
        unsigned uLen = str.getLength();
        setLength(uLen);
        setSize(uLen + 1U);
        getStr() = str.getStr();
    }

    m_pRefCout = str.getRefAddr();
    refCoutAdd();
}

CMyString::CMyString(const char *str)
{
    initString(str);
    initRefCout();
}

CMyString::~CMyString()
{
    refCoutDel();
    if (!getIsNull())
    {
        if (getRefCout() == 0)
        {
            delete[] getStr();
        }
        setIsNull(true);
        setLength(0U);
        setSize(0U);
    }
    
    clearRefAddr();
}

void CMyString::initRefCout()
{
    m_pRefCout = new int[1];
    *m_pRefCout = 1;
}

void CMyString::setRefCout(const int cout)
{
    *m_pRefCout = cout;
}

int CMyString::getRefCout()
{
    return *m_pRefCout;
}

int * CMyString::getRefAddr()
{
    return m_pRefCout;
}

void CMyString::refCoutAdd()
{
    setRefCout(getRefCout() + 1);
}

void CMyString::refCoutDel()
{
    setRefCout(getRefCout() - 1);
}

void CMyString::clearRefAddr()
{
    if (getRefCout() == 0)
    {
        delete[] getRefAddr();
    }
}

inline char*& CMyString::getStr()
{
    return m_pStr;
}

inline unsigned CMyString::getLength() const
{
    return m_uLenth;
}

inline unsigned CMyString::getSize() const
{
    return m_uSize;
}

inline void CMyString::setStr(const char *str)
{
    strcpy(getStr(), str);
}

inline void CMyString::setLength(const unsigned length)
{
    m_uLenth = length;
}

inline void CMyString::setSize(const unsigned size)
{
    m_uSize = size;
}

inline bool CMyString::getIsNull() const
{
    return m_bIsNull;
}

inline void CMyString::setIsNull(bool b)
{
    m_bIsNull = b;
}

CMyString& CMyString::myStrcpy(CMyString& str)
{
    if (getIsNull())
    {
        if (!str.getIsNull())
        {
            if (getRefCout() != 1)
            {
                refCoutDel();
                initRefCout();
            }
            initString(str.getStr());
        }
    }
    else
    {
        if (str.getIsNull())
        {
            if (getRefCout() != 1)
            {
                refCoutDel();
                initRefCout();
            }
            setIsNull(true);
        }
        else
        {
            if (getRefCout() == 1)
            {
                unsigned uLen = str.getLength() + 1U;
                if (getSize() >= uLen)
                {
                    setStr(str.getStr());
                    setLength(str.getLength());
                }
                else
                {
                    delete[] getStr();
                    initString(str.getStr());
                }
            }
            else
            {
                refCoutDel();
                initRefCout();
                unsigned uLen = str.getLength() + 1U;
                setLength(str.getLength());
                initString(str.getStr());
            }
        }
    }

    return *this;
}

CMyString& CMyString::myStrcat(CMyString& str)
{
    if (getIsNull())
    {
        if (getRefCout() != 1)
        {
            refCoutDel();
            initRefCout();
        }
        if (!str.getIsNull())
        {
            initString(str.getStr());
        }
    }
    else
    {
        if (!str.getIsNull())
        {
            unsigned uLen = getLength() + str.getLength() + 1U;
            char *pszTmp = new char[uLen];
            strcpy(pszTmp, getStr());
            strcat(pszTmp, str.getStr());

            if (getRefCout() == 1)
            {
                if (getSize() >= uLen)
                {
                    setStr(pszTmp);
                    setLength(uLen - 1);
                }
                else
                {
                    delete[] getStr();
                    initString(pszTmp);
                }
            }
            else
            {
                refCoutDel();
                initRefCout();
                initString(pszTmp);
            }

            delete[] pszTmp;
        }
    }

    return *this;
}

inline void CMyString::initString(const char* str)
{
    if (str == nullptr)
    {
        setIsNull(true);
        setLength(0U);
        setSize(0U);
    }
    else
    {
        setIsNull(false);
        unsigned uLen = strlen(str) + 1U;
        setLength(uLen - 1U);
        setSize(uLen);
        getStr() = new char[uLen];
        setStr(str);
    }
}

void CMyString::clearFormatHeap()
{
    if (m_pFormatStr != nullptr)
    {
        delete[] m_pFormatStr;
        m_pFormatStr = nullptr;
    }
}

CMyString& CMyString::myStrUpper()
{
    if (!getIsNull())
    {
        
        if (getRefCout() == 1)
        {
            char *pchStr = getStr();
            while (*pchStr != '\0')
            {
                if (*pchStr >= 'a' && *pchStr <= 'z')
                {
                    *pchStr -= 32;
                }
            }
        }
        else
        {
            refCoutDel();
            initRefCout();
            char *psz = new char(getLength() + 1U);
            setStr(psz);
            char *pchStr = getStr();
            while (*pchStr != '\0')
            {
                if (*pchStr >= 'a' && *pchStr <= 'z')
                {
                    *pchStr -= 32;
                }
            }
        }
    }

    return *this;
}

CMyString& CMyString::myStrLower()
{
    if (!getIsNull())
    {
        if (getRefCout() == 1)
        {
            char *pchStr = getStr();
            while (*pchStr != '\0')
            {
                if (*pchStr >= 'A' && *pchStr <= 'Z')
                {
                    *pchStr += 32;
                }
            }
        }
        else
        {
            refCoutDel();
            initRefCout();
            char *psz = new char(getLength() + 1U);
            setStr(psz);
            char *pchStr = getStr();
            while (*pchStr != '\0')
            {
                if (*pchStr >= 'A' && *pchStr <= 'Z')
                {
                    *pchStr += 32;
                }
            }
        }
    }

    return *this;
}

inline void CMyString::myStrClear()
{
    setIsNull(true);
}

inline const char* CMyString::myFindSubStr(CMyString& str)
{
    if (str.getLength() > getLength())
    {
        return nullptr;
    }
    else if (getIsNull() || str.getIsNull())
    {
        if (getIsNull() && str.getIsNull())
        {
            return getStr();
        }
        else
        {
            return nullptr;
        }
    }
    else
    {
        //标记是否搜索成功
        const char *isSubStr = nullptr;
        //字符串
        const char *pNowstr = getStr();
        //需要被搜索的字符串
        const char *pFindStr = str.getStr();
        //调至字符串和被搜索的字符串末尾
        while (*pNowstr != '\0')
        {
            pNowstr++;
        }
        pNowstr--;

        while (*pFindStr != '\0')
        {
            pFindStr++;
        }
        pFindStr--;
        //记录一下被搜索的字符串的尾地址
        const char *pFindStrLastPointer = pFindStr;
        //当字符串为开始地址的时候结束
        do
        {
            //如果被搜索的字符串为开始位置
            if (pFindStr == str.getStr() - 1)
            {
                isSubStr = pNowstr + 1;
                break;
            }
            else if (*pNowstr != *pFindStr)
            {
                pNowstr--;
            }
            else//如果有相同的字符串的时候
            {
                do
                {
                    if (*pNowstr != *pFindStr)
                    {
                        pFindStr = pFindStrLastPointer; //如果还没到结束就不相等了,把字符设为尾巴
                        break;
                    }
                    else
                    {
                        pFindStr--;
                        pNowstr--;
                    }
                } while (pFindStr != str.getStr() - 1);//当被搜索的字符串为开始时表明相等

            }
        } while (pNowstr != getStr() - 1);

        //如果两个都结束表示查找的全匹配
        if (pNowstr == getStr() - 1 && pFindStr == str.getStr() - 1)
        {
            isSubStr = getStr();
        }

        return isSubStr;
    }
}

const char *CMyString::getBuff()
{
    if (getIsNull())
    {
        return nullptr;
    }
    else
    {
        return getStr();
    }
}

const char * CMyString::getSubStrPointer(CMyString & str)
{
    return myFindSubStr(str);
}

const int CMyString::myStrcmp(CMyString& str)
{
    if (getIsNull() || str.getIsNull())
    {
        if (getIsNull() && str.getIsNull())
        {
            return 0;
        }
        else
        {
            return -1;
        }
    }
    return strcmp(getStr(), getStr());
}

const bool CMyString::checkIsPlalindrome()
{
    if (getLength() <= 2U)
    {
        return false;
    }

    const char *pStr = getStr();
    unsigned uI = 0;
    unsigned uJ = getLength() - 1U;
    while ((*(pStr + uI) == *(pStr + uJ)) && (uI <= uJ))
    {
        uI++;
        uJ--;
    }
    if (uI > uJ)
    {
        return true;
    }
    else
    {
        return false;
    }
}

string CMyString::ValueOf(bool b)
{
    clearFormatHeap();
    char *szS = new char[6];
    m_pFormatStr = szS;
    if (b == true)
    {   
        strcpy(szS, "true");
    }
    else
    {
        strcpy(szS, "false");
    }

    return m_pFormatStr;
}

string CMyString::ValueOf(char c)
{
    clearFormatHeap();
    char *szS = new char[2];
    m_pFormatStr = szS;
    sprintf(szS, "%c", c);
    return m_pFormatStr;
}

string CMyString::ValueOf(double d)
{
    clearFormatHeap();
    char *szS = new char[100];
    m_pFormatStr = szS;
    sprintf(szS, "%E", d);
    return m_pFormatStr;
}

string CMyString::ValueOf(float f)    //4.5f ==> "4.5"
{
    clearFormatHeap();
    char *szS = new char[100];
    m_pFormatStr = szS;
    sprintf(szS, "%f", f);
    return m_pFormatStr;
}

string CMyString::ValueOf(int i)     //123 ==> "123" 
{
    clearFormatHeap();
    char *szS = new char[100];
    m_pFormatStr = szS;
    sprintf(szS, "%d", i);
    return m_pFormatStr;
}

string CMyString::ValueOf(long i)    //123 ==> "123" 
{
    clearFormatHeap();
    char *szS = new char[100];
    m_pFormatStr = szS;
    sprintf(szS, "%ld", i);
    return m_pFormatStr;
}

string CMyString::ValueOf(short i)    //123 ==> "123" 
{
    clearFormatHeap();
    char *szS = new char[100];
    m_pFormatStr = szS;
    sprintf(szS, "%d", i);
    return m_pFormatStr;
}

string CMyString::ValueOf(const char* data) //char[] = "123" ==> string CMyStrig::"123" 
{
    clearFormatHeap();
    int lenth = strlen(data) + 1;
    char *szS = new char[lenth];
    m_pFormatStr = szS;
    sprintf(szS, "%s", data);
    return m_pFormatStr;
}


/*
string CMyString::CopyValueOf(const char* data, int offset, int count) //char[] = "123" ==> string CMyStrig::"123" 
{

}

string CMyString::Format(CMyString format, ...)  //("%d", 123) ==> string CMyStrig::"123" 
{
}
*/

char *CMyString::m_pFormatStr = nullptr;
0 条评论
发表一条评论