C++学习:第三章C++语言基础 - (八)运算符重载

1. 多个运算符连续,系统会按照一定的顺序逐个处理

Teacher t;
cout << ~t << endl;

2. 运算符重载的两种情况

不在类中完成

Teacher& operator ~ (const Teacher& t){
    ...
    return t;
}

在类中完成

bool T::operator!(){
    return (n==0);
}

3. 当指针成员指向动态内存时

指针成员指向动态内存,以下三个函数必须自己写

  • 拷贝构造
  • 等号复制
  • 析构函数

 

4. = -> [] () 只能用成员函数重载

 

类中只有一个对象,且能访问:单例模式

内存释放:创建计数器的方式避免重复释放

#include <iostream>
#include <string>

using namespace std;

struct date{
    int year;
    int mouth;
    int day;
};

struct Person{
    string name;
    int age;
    bool gender;
    double salary;
    date birth;
    Person(){cout << "创建Person对象  " << this << endl;}
    ~Person(){cout << "释放Person对象  " << this << endl;}
};


class autoptr{

public:

    //注:这两个变量应该是私有的,只是为了演示方便
    Person* p;
    int     cnt;

    autoptr(Person* p):p(p),cnt(1){}

    //这个类的->有一个隐含的问题,就是复制!
    //因为复制时初始化另一个对象并没有为其开辟新的空间,只是指向被复制对象的内存地址
    //因此在释放时候就会出现同一个内存被释放两边的问题
    //因此引入了 cnt 计数器,只有第一次开辟该内存时才是可以被释放的
    autoptr(const autoptr& a):p(a.p){cnt = a.cnt+1;}
    ~autoptr(){if(cnt==1)delete p;}

    //这个运算符永远无参
    //C++规定:希望通过该运算符访问谁的成员就返回谁的地址
    Person* operator->(){
        return p;
    }

    //返回它所指向对象本身,因此返回值是引用,不是复制一份
    //C++规定:希望通过该运算符访问谁的成员就返回谁的对象
    Person& operator*(){
        return *p;
    }
};



int main(){

    // 等价于autoptr a(new Person);
    // 这其实就是初始化了一个 Person 然后利用autoptr(Person* p);
    // 这个构造函数赋值给a
    autoptr a = new Person;

    //等价于 (*a.p).age = 99;
    //编译器处理:a.operator->()->name
    a->age = 120;
    cout << a->age << endl;

    a->name = "abc";
    cout << (*a).name << endl;

    (*a).age = 11;
    autoptr b = a;
    cout << b.cnt << endl;

    getchar();
    return 0;
}

 

内存释放:开辟两个空间

#include <iostream>
#include <string>

using namespace std;

class Stack{
    typedef unsigned int uint;
    typedef string T;
    T* men;
    uint max;
    uint len;
public:
    Stack(uint n): men(new T[n]),max(n),len(0) {}

    //开辟两个空间避免重复释放
    Stack(const Stack& s): men(new T[s.max]), max(s.max),len(s.len) {}

    uint max_size()const{
        return max;}

    uint size()const{
        return len;}

    Stack& push(const T& e){
        if (len>=max)
            throw 0;
        men[len++] = e;
        return *this;}

    T pop(){
        if(len==0)
            throw 1;
        return men[--len];}

    void print()const{
        for(uint i=0; i<len; i++){
            cout << men[i] << " ";}
            cout << endl;}

    ~Stack(){
        delete[] men;};

    Stack& operator=(const Stack& s2){

        //这是避免自己给自己赋值的情况
        if(this == &s2){
            return *this;}
        this->len = s2.len;
        this->max = s2.len;
        delete [] men;
        this->men = new(T [this->max]);
        for (uint i=0; i<len; i++){
            men[i] = s2.men[i];
        }
        return *this;
    }
};


int main(){

    Stack s1(5);
    Stack s2(s1);

    //这个写法在调用时会复制一份,但在释放时就会重复释放
    //s1.operator(s2)
    s1 = s2;

    getchar();
    return 0;
}

 

前后 ++ -- 、double 等运算符重载

#include <iostream>
#include <string>

using namespace std;


class F{
	int n;
	int d;
public:
	F(int n=0, int d=1):n(n),d(d){}
	friend ostream& operator << (ostream& o, const F& f){
		o << f.n << " / " << f.d ;
		return o;
	}

	F& operator ++ (){
		n += d;
		return *this;
	}

	F operator ++ (int){//为了区分前后++,引入哑元
		F old(*this);
		n += d;
		return old;
	}

	friend F& operator -- (F& f){
		f.n -= f.d;
		return f;
	}

	friend F operator -- (F& f, int){
		F old(f);
		f.n -= f.d;
		return old;
	}

	//类型转换运算符函数的转换返回类型省略
	//因为返回值类型总是和重载的类型函数相同
	operator double (){
		return 1.0*n/d;
	}

	operator bool (){
		return n;
	}
}


int main(){

	F f1(2,5), f2(4,9), f3(17,3);
	++f1;	//f1.operator++();
	f2++;	//f2.operator++(0); //为了区分前后++,引入哑元

	--f1;	//f1.operator--();
	f2--;	//f2.operator--(0);

	double(f1);

	getchar();
	return 0;
}

 

实参初始化形参

class F{
    int n;
    F(int n):n(n){};
}
void func(F f){}
int mian(){
    func(6);
    return 0;
}

//上面的写法是对的,其实是中间省略了一步
// func前后 ++ -- 、double ()等运算符重载

 

重载[] ()

#include <iostream>
#include <string>

using namespace std;

class A{
public:
	typedef unsigned int uint;
private:
	int* p;
	uint n;
public:
	A(uint n):n(n){
		p = new int[n];
		if (NULL == p){
			throw 0;
			memset(p, 0, n*4);
		}
	}

	~A(){
		delete[] p;
	}
	
	uint size()const{
		return n;
	}

	int& operator[] (uint i)const{

		//越界检查
		if (i >= n){
			throw 1;
		}

		//这个地方不会有递归
		//因为调用函数是A类型
		//返回函数是 int* 类型的
		return p[i];
	}
	
	int& operator[] (const char* c)const{

		int i = atoi(c);
		if (i <0 || i >= n){
			throw 1;
		}
		return p[i];
	}

	void operator() (int v){
		for (uint i=0; i<n; i++){
			p[i] += v;
		}
	}

	void operator() (const char* s){
		int v = atoi(s);
		for (uint i=0; i<n; i++){
			p[i] += v;
		}
	}
};

ostream& operator<< ( ostream& o, const A& a ){
	o << "{ ";
	for (int i=0; i<a.size(); i++){
		cout << a[i] << ' ';
	}
	o << "}";
	return o;
}


int main(){

	A x(5), y(8);
	x[2] = 20;		//x.operator[](2);
	y["6"] = 66;	//y.operator[](6);
	x(3);		//x.operator()(3);
	y("5");		//y.operator()(5);

	getchar();
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值