C++学习笔记08

复习:

   运算符重载:

    编译器把运算符当作函数

      全局

        函数名:operator 运算符

        参数表:所有操作数

        返回类型:合乎情理即可

      成员

        函数名:operator 运算符

        参数表:除第一个之外的操作数,当前对象作为第一个操作数

        返回类型:合乎情理即可

      编译器会尝试这两种形式([]()=->type只当成员函数),如果两种都有或者都没有,编译失败。每个运算符函数只允许有其中一种形式。

      operator type()不写返回类型却胜写返回类型,因为函数名里面已经包含返回类型

      ostream& operator<<(ostream& o,const A& x);

      istream& operator>>(istream& i,A& x);

        这两个只能写成非成员函数。如果需要访问对象的私有成员,就要在类里把他们声明成友元

      const对象只能调用const成员函数(const在参数表后)

        const成员函数里的this是const A* const,而普通成员函数的this是A* const

        const对象中的mutable修饰的数据成员允许修改

      双目运算符重载:

        a+b: a.operator+(b) operator+(a,b)

      单目运算符重载:

        &a: a.operator& (),operator&(a)

      指针

        const int* p;//p指向const int

        int const* p;//p指向const int

        int* const p;//p本身是const

        const int* const p;//p本身是const而且指向const int

运算符重载

  ->返回内部某个结构变量的地址,编译器通过这个地址执行真正的->操作访问里面的成员

#include<iostream>
using namespace std;

struct POINT{
    int x;
    int y;
};
class Pos{
    POINT p;
public:
    Pos(int x=0,int y=0){p.x = x,p.y=y;}
    void move(int cx,int cy){p.x+=cx,p.y+=cy;}
    void moveto(int x,int y){p.x = x,p.y=y;}
    POINT* operator->(){return &p;}
};

int main()
{
    Pos a(20,80);
    cout<<a->x<<","<<a->y<<endl;
    a.move(30,-10);
    cout<<a->x<<","<<a->y<<endl;
    system("pause");
}

  new/delete重载负责内存的分配和释放,编译器会在内存分配之后调用构造函数,内存释放之前调用析构函数,有[]和没有[]是不同的运算符

#include<iostream>
#include<cstdio>
using namespace std;

class A{
    int data;
public:
    A(int d=0):data(d){cout<<"A("<<data<<")"<<endl;}
    ~A(){cout<<"~A()"<<data<<endl;}
    void* operator new(size_t bytes){
    cout<<"bytes="<<bytes<<endl;
    return malloc(bytes);}
    void operator delete(void* p){
        cout<<"p="<<p<<endl;
        return free(p);
    }

    void* operator new[](size_t bytes){
    cout<<"bytes="<<bytes<<endl;
    void* p = malloc(bytes);
    cout << "malloc:"<<p<<endl;
    return p;
    }
    void operator delete[](void* p){
        cout<<"p="<<p<<endl;
        return free(p);
    }
};

int main()
{
    A* p= new A;//operator new sizeof(A)
    cout<<"sizeof A="<<sizeof(A)<<endl;
    cout<<"p="<<p<<endl;
    delete p;p=NULL;//operator delete(p)
    cout<<"-----------------------"<<endl;
    p = new A[3];
    cout<<"p="<<p<<endl;
    cout<<"*p="<<*((int *)p-1)<<endl;//数组前一位存数组个数
    delete[] p;p=NULL;
    system("pause");
}

  ++/--

    前++前--,正常的单目运算符用法,计算结果就是变量的最新值因此可以直接拿这个对象做计算结果

      成员:A& operator++(){... return *this;}

      友元:friend A& operator++(A& x){... return x;}

    后++后--,非正常用法,计算结果是对象的旧值,必须用临时空间来保存,不能拿对象本身作为计算记过,定义运算符函数时需要一个多余的int哑元。

      成员:A operator++(int){... return old;}

      友元:friend A operator++(A x,int){... return old;}

  运算符重载一定要合乎情理。运算符重载是自己规定运算符对于特定类型的操作数应该如何工作,对于基本类型的运算不应该重载,不应该创造新的运算符,不应该改变操作数的个数。

  有些运算符不允许重载:. , .* , ?:,::,typeid,sizeof  

#include <iostream>
using namespace std;

class R{//分数类
    int n;
    int d;
public:
    friend ostream&operator<<(ostream&o,const R&x){
        return o<<x.n<<"/"<<x.d;
    }
    R(int n,int d):n(n),d(d){}
    R& operator++(){//成员形式的前++
        n+=d;
        return *this;
    }
    //非成员形式(友元形式)的前--
    friend R& operator--(R& x){
        x.n=x.n-x.d;
        return x;
    }
};

int main()
{
    R a(3,4);
    cout<<"a="<<a<<endl;
    cout<<"a="<<++ ++ a<<endl;//operator++(a),a.operator++()
    cout<<"a="<<-- -- a<<endl;
    system("pause");
}
#include<iostream>
using namespace std;

class R{
    int n;
    int d;
public:R(int n=0,int d=1):n(n),d(d){}
       friend ostream& operator<<(ostream&,const R&);
       R operator++(int){//返回类型不应该加引用
            //虚假的形参 int 用于与前++区分,是哑元
           R old = *this;
            n+=d;
            return old;
        }
};
ostream& operator<<(ostream& o, const R& x)
{
    return o<<x.n<<"/"<<x.d;
}



int main()
{
    R a(3,5);
    cout<<"a++ ="<<a++<<endl; //a.operaotr(0)后++会传一个无用的参数0
    cout<<"a="<<a<<endl;
    system("pause");
}
posted @ 2016-05-09 20:13  Visions  阅读(171)  评论(0编辑  收藏  举报