• c++要点


    c++基础知识

      从一个基本的CMyString类讲起,分析了

        构造函数

        拷贝构造函数

        析构函数

        "="、"+="、"+"、左"++"、右"++"操作符重载

        "<<"输出流友元函数重载

      1、实现过程要关注内存泄露(析构)、非法输入值处理(“赋值重载”)、内存溢出异常处理(“赋值”重载)。

      2、操作符重载特别注意返回值类型和返回方式

      面向对象的三大特征:封装、继承和多态。多态特征将在工厂模式里强调。

    class CMyString
    {
    public:
        CMyString(const char *pData = NULL)
        {
            /*
            构造函数
                作用:完成对象的初始化
                调用顺序:
                        a. 静态成员对象的构造函数。因为静态成员是与类直接相关的,在类内声明,在类的外部定义,并且只初始化一次。
                        b. 抽象基类的构造函数(按继承的顺序)
                        c. 虚拟基类的构造函数(按继承的顺序)
                        d. 非虚拟基类的构造函数(按继承的顺序)
                        e. 非静态成员对象的构造函数(按声明的顺序)
                        f. 调用类的构造函数。
            */
            if (pData == NULL)
            {
                m_pData = new char[1];
                m_pData[0] = '';
            }
            else
            {
                //字符串数组的拷贝拷贝方式
                int length = strlen(pData);
                m_pData = new char[length + 1];
                strcpy(m_pData, pData);
            }
        }
    
        CMyString(const CMyString& str)
        {
            /*
             *    拷贝构造函数
             *        1、深拷贝与浅拷贝
             *            当类成员变量为指向堆空间的指针时,需要采用深拷贝,防止两个对象之间的干扰
             *        2、深拷贝过程
             *            为类成员指针分配新的堆上空间
             *            执行内容拷贝
             *
             */
            int length = strlen(str.m_pData);
            m_pData = new char[strlen(str.m_pData) + 1];
            strcpy(m_pData, str.m_pData);
        }
    
        ~CMyString(void)
        {
            /*
             *    析构函数
             *        1、默认析构函数
             *        2、当类成员使用堆上空间时,需要自定义析构函数,防止内存泄露
             */
            delete [] m_pData;    
        }
    
        CMyString& operator=(const CMyString& str)
        {
            /*
             *    =操作符重载
             *        1、要点
             *            a. 返回类型声明为该类型的引用,并且在函数结束前返回对象自身的引用(*this)
             *            b. 传入参数为常量引用
             *            c. 拷贝时首先需要释放堆上空间,防止内存泄露
             *            d. 判断参数对象与当前对象是不是同一个对象
             *        2、重载:匹配同名函数的参数列表,返回值类型不在考虑范围
             *        3、成员函数参数列表隐含了this指针,指向当前对象
             */
    
            if (this == &str)
            {
                //判断参数对象与当前对象是不是同一个对象
                return *this;
            }
    
            //释放堆上空间,防止内存泄露
            delete [] m_pData;
            m_pData = NULL;
    
            int length = strlen(str.m_pData);
            m_pData = new char[length + 1]; //bug: 当内存溢出时,抛出异常,对象失效
            strcpy(m_pData, str.m_pData);
    
            //返回对象自身的引用
            return *this;
        }
    
        CMyString& operator += (CMyString& rhs)
        {
            /*
             *    +=操作符重载
             *        1、返回当前类型的引用,函数结束时返回当前实例的引用*this
             */
            CMyString temp; //定义临时变量,防止内存溢出而抛出异常
    
            int length;
            length = strlen(m_pData) + strlen(rhs.m_pData);
    
            temp.m_pData = new char[length + 1];
            strcpy(temp.m_pData, m_pData);
            strcat(temp.m_pData, rhs.m_pData); //字符串的拼接
            
            char *pTemp = m_pData;
            m_pData = temp.m_pData;
            temp.m_pData = pTemp; //将当前实例的堆空间赋值给临时变量,在函数退出时析构
    
            return *this;
        }
    
        CMyString operator + (CMyString& rhs)
        {
            /*
             * + 操作符重载
             *         返回右值,也即将临时对象返回
             *         返回过程:
             *             a. 调用拷贝构造函数,生成匿名临时对象,用于返回
             *             b. 析构局部对象
             */
    
            CMyString ret;
            int length;
    
            length = strlen(m_pData) + strlen(rhs.m_pData);
            ret.m_pData = new char[length + 1];
            strcpy(ret.m_pData, m_pData);
            strcat(ret.m_pData, rhs.m_pData);
            
            return ret;
        }
    
        CMyString& operator ++()
        {
            /*
             *    前加
             *        返回引用,作为左值
             */
            int length;
            char *pTemp = m_pData;
    
            length = strlen(m_pData) * 2;
    
            m_pData = new char[length + 1];
            strcpy(m_pData, pTemp);
            strcat(m_pData, pTemp);
    
            delete [] pTemp;
    
            return *this;
        }
    
        CMyString operator ++(int rhs)
        {
            /*
             *    后加
             *        形参:标识重载函数
             *        返回值:返回对象,作为右值
             */
            CMyString ret = *this;
    
            int length;
            
            char *pTemp = m_pData;
    
            length = strlen(m_pData) * 2;
    
            m_pData = new char[length + 1];
            strcpy(m_pData, pTemp);
            strcat(m_pData, pTemp);
            
            delete [] pTemp;
    
            return ret;
        }
    
        //友元
        //    输出流重载
        //    作用:扩展外部函数的访问权限
        friend ostream& operator<< (ostream& os, const CMyString& str);
    
    private:
        char *m_pData;
    };
    
    //友元函数的实现
    ostream& operator<< (ostream& os, const CMyString& str)
    {
        os << str.m_pData;
        return os;
    }

        

  • 相关阅读:
    __doPostback在客户端控件中的作用
    BlogEngine学习二:基于ICallbackEventHandler的轻量级Ajax方式
    JS操作XML数据备忘
    JS解析DataSet.GetXML()方法产生的xml
    JS中的prototype的使用方式
    实体类的二进制序列化
    PostgreSQL的.NET驱动程序Npgsql中参数对象的一个Bug
    PDF.NET的SQL日志
    PostgreSQL的PDF.NET驱动程序构建过程
    使用XSD编写具有智能提示的XML文件(以SQLMAP脚本为实例)
  • 原文地址:https://www.cnblogs.com/zjgtan/p/3834539.html
Copyright © 2020-2023  润新知