标准C++04

一、运算符重载
    C++中是运算符当作函数来看待,所以C++中的运算符可以重载,这样可以让类对象支持运算符,对类对象进行定制化操作。
    例如:string类就支持很多运算符来代替标准库中的函数。
        = strcpy
        += strlen
        ==|!=|>=|<= strcmp

二、双目录运算符重载
    假如:Test a,b; a+b操作可以调用两种函数
    Test的成员函数:a是触发者,b是参数
    Test operator+(cosnt Test& b) const
    {
        return a+b; // 返回临时对象
    }

    全局函数:a,b都是参数
    Test operator+(const Test& a,const Test& b)
    {
        return a+b; // 返回临时对象
    }

    注意:如果成员运算符函数和全局函数运算符函数都实现,调用时可能会产生二义性错误,成员或全局实现一个即可。

    友元函数:
        在类外的函数想访问类的私有成员时,需要把函数声明类的友元函数,但友元函数只有朋友,只有访问权,没有实际的拥有权。
        
    友元声明:
        把函数的声明在类中写一份,然后在函数的声明前加friend关键字。
        友元函数可以让运行符是全局函数,也可以保持类的封装性。
    
三、赋值类型的运算符
    成员函数
    Test& operator=(cosnt Test& b) // 隐藏的有
    {
        a = b;
        return a;
    }
    全局函数
    Test& operator=(Test& a,const Test& b) // a不能有const属性
    {
        a = b; // 返回临时对象
        return a;
    }
    1、如果是某种类型直接为类对象赋值,单参构造也可以达到赋值运算符的效果。
        String str = "hehe"; // 调用单参构造
        str = "hehe"; // 赋值运算符
    2、如果对象的成员中没有指针成员,默认的赋值函数即可。

四、输入输出运算符重载
    使用输入输出运算符时由于触发运算符函数的是cout、cin,我们无法修改cont和cin的代码,所心只能实现为全局运算符函数。
    ostream& operator<<(ostream& os,cosnt Test& t)
    {
        return os << t.m1 << t.m2;
    }
    istream& operator<<(istream& is,const Test& t)
    {
        return is >> t.m1 >> t.m2;
    }
    注意:外部的cin和cout可能需要连接的输入或输出因此需要把os和is返回,由于在输入输出过程中需要记录错误标志,因此不能加const。
五、单目运算符重载
    ~ ! ++ --
    成员函数
        Test operator!(void)
        {
            !this;
            return Test(); // 返回临时对象
        }
    全局函数
        Test operator!(Test& t)
        {
            !t;
            return Test(); // 返回临时对象
        }
    前++/--
        Test& operator++(void)
        {
            this++;
            return *this;
        }
        Test& operator++(Test& t)
        {

        }
    后++/--
        Test operator++(int)// 哑元,为了区别前++/--
        {
            Test t = *this;
            this++;
            return t;
        } 
六、特殊运算符重载
    1、下标运算符[],该运算符重载后可以让对象像数组一样使用,必须重载为成员函数。
    2、解引用运算符*、成员访问运算符->,该运算符重载后可以让对象像指针一样使用。
    3、函数调用运算符(),该运算符重载后可以让对象像函数一样使用。
    4、new/delete/new[]/delete[]运算符重载
        1、C++缺省的内存管理器速度比较慢,重载运算符可以使用malloc/free作为底层的内存管理器,提高运行速度。

        2、new运算在失败时会产生异常,而每次使用new时为了安全都就应该捕获异常,而重载new运算符后只需要在操作符函数中捕获一次并处理即可。

        3、一些字节数较少的类的对象,频繁使用new时会产生内存碎片,而重载new运算符后,可以适当的扩大申请的字节数,降低内存碎片产生的机率。

        4、重载new和delete后,可以函数中记录分配和释放的内存信息,方便查找内存泄漏。
        void* operator new(size_t size)
        {

        }

七、智能指针
    常规指针的缺点:
        当一个指针变量离开它的作用域,只有该指针所占用内存会被释放,而它指向的堆内存能否释放就不一定了,在一些特殊情况下delete/free没有执行,就会造成内存泄漏。
    智能指针的优点:
        智能指针就是封装了常规指针的类类型对象,当它离开作用域时它的析构函数就会自动执行,析构函数会负责释放常规指针所指向的堆内存。
    auto_ptr:标准库中封装好模板类,实现了常规的基本功能。
    头文件:#include <memory>
    用法:auto_ptr<指向的类型> 指针变量名(new 类型);
        之后就可以像常规指针一样使用智能指针了。
    智能指针的缺点:
        一个指针只能指向一个对象,但常规指针可以多个指针指向一个对象。
        不能跨作用域使用,一但离开作用域智能指针就会释放它指向的对象。
        智能指针不能放入容器中。
八、重载运算符的限制
    1、只能重载为成员函数的运算符
        = [] () -> *
    2、只能重载为全局函数的运算符
        << >>
    3、不能重载的运算符
        ::  域限定符
        .   直接成员访问运算符
        ?:  三目运算符
        sizeof  字节数运算符
        typeid  类型信息运算符
    4、重载运算符时不能修改运算符的优先级。
    5、重载运算符时不能改变参数的数量
    6、无法为基本类型重载运算符
    7、不能发明新的运算符

个人建议:
    1、重载运算符时要根据运算符实际的功能和意义确定参数、返回值,是否使用const,不否使用引用,是否返回临时对象。

    2、重载运行符时要符合情理、要有意义、以实际用途为前提。

    3、重载运算符是为了让对象的操作更简单方便,提高代码可读性,而不是为了炫技。

    4、重载运算符的功能要与默认的一致,不要出现反人类的操作。

作业:
    实现一个功能相对完成String类。
posted @ 2020-09-19 10:38  斯立扑  阅读(110)  评论(0)    收藏  举报