c++第四天(运算符重载)

运算符重载
运算符重载有两种方式

  1. 使用类的成员函数
  2. 使用全局函数
    内置类型运算符的含义是不可更改的
+ 运算符的重载

可以使用上面

class Person{
public:
    int age = 0;
    Person(){};
    Person(int age):age(age){};

	//使用类的成员函数进行运算符重载
    Person operator+(Person& p){
        Person tmp;
        tmp.age = this->age + p.age;
        return tmp;
    }
};
//使用全局函数进行运算符重载
Person operator-(Person& p1,Person& p2){
    Person tmp;
    tmp.age = p1.age - p2.age;
    return tmp;
}

//运算符重载作为函数,同样可以提供多个版本
Person operator-(Person& p,int a){
    Person tmp;
    tmp.age = p.age - a;
    return tmp;
}
int main(){
   Person p1(10);
   Person p2(20);
   Person p3 = p2 + p1;
   Person p4 = p2 - p1;
   cout << p3.age << endl;	//30
   cout << p4.age << endl;	//10
}
>> 运算符重载
// << 运算符重载不能作为成员函数,第一个参数必须是输出流
ostream& operator<<(ostream& out, Person& p){
    out << "p.age=" << p.age;
    return out;
}
int main(){
cout << p3 << endl;	//p.age=30
}
前置和后置递增递减运算符重载 ++ 为例
class Person{
public:
    int age = 0;
    Person(){};
    Person(int age):age(age){};
    Person&  operator++(){    //前置运算符
        ++this->age;
        return *this;
    };

    Person operator++(int){ //后置运算符
        Person tmp = *this;	//创建了一个临时对象
        this->age++;
        return tmp;
    }
};

1:前置运算符返回的是引用,传入参数没有占位符
2:后置运算符用了一个占位符,返回的是值
后置运算符由于创建了一个中间变量,所以效率不如前置
那么,前置++为什么要返回引用?看下面这个例子

Person p;	//假如p的前置++运算符重载返回的不是引用
cout << ++(++p) << endl;
cout << p.age << endl;	//输出是1

之所以会这样,是因为第一次++返回的已经不是原先的对象了,再次++,是对新的对象+1
后置++为什么不返回引用呢?
后置返回的是一个临时变量,临时变量在返回后会被销毁,如果是引用,那么引用了一个被销毁的变量,会出现野指针异常。

指针运算符重载(智能指针)

在c++中,使用new申请的内存是需要手动释放的,但许多时候会记不得~
于是乎,就有了智能指针,帮你释放内存
当智能指正被析构,所指向的对象也会被析构
使用 ->* 的重载我们就可以实现智能指针的功能

template<typename T>
class smartPoint{
    T* content;
public:
    smartPoint(T* content):content(content){};
    T* operator->(){
        return this->content;
    }
	
	//重载解引用运算符
    T& operator*(){
        return *(this->content);
    }
    //指针被释放的时候,内部的content所指向的对象也被释放了
    ~smartPoint(){
        if (this->content != NULL){
            delete this->content;
            this->content = NULL;
        }
    }
};

class Person{
public:
    int age = 10;
    void say(){
        cout << "hello world" << endl;
    }
};

int main(){
    smartPoint<Person> s(new Person);
    cout << s->age << endl;	//这里按理来说,应该是 ->->,第一个->返回Person*,第二个->用于取值,编译器帮我们优化成一个了。
    (*s).say();
}
赋值运算符 = 重载

c++默认也会重载 = 运算符,但是对于指针类型,只会对指针本身进行拷贝,这样析构函数时,会对指针指向的堆区内存重复释放,造成错误,这个时候就需要我们重载 = 运算符。

class Person {
public:
	Dog* dog;
	Person(string name) {
		this->dog = new Dog(name);
	};
	Person& operator=(const Person& p) {
		if (this->dog != NULL) {
			delete this->dog;
		}
		this->dog = new Dog(p.dog->name);
		return *this;
	}
	~Person() {
		if (this->dog != NULL) {
			delete this->dog;
			this->dog = NULL;
		}
	}
};

这里就要吐槽一下clion了,重复delete一块堆区内存居然不报错!!!,还有,visual studio代码编辑器能做的好用些么???

索引运算符重载 [ ]
int& operator[](int index){
	return this->array[index];
}

这里需要注意的就是要返回引用,只有引用才能定位到数组要赋值的那块内存。

比较运算符重载
class Person{
    string name;
    int age;
public:
    Person(string name,int age):name(name),age(age){};
    bool operator==(Person& p){
        if(p.age == this->age && p.name == this->name){
            return true;
        } else{
            return false;
        }
    }
    bool operator!=(Person& p){
        if(p.age == this->age && p.name == this->name){
            return false;
        } else{
            return true;
        }
    }
};
函数运算符 () 重载
class Person{
public:
    void operator()(string str){
        cout << str << endl;
    }
};

int main(){
    Person()("hello world");
}

这里使用了匿名对象,匿名对象调用了函数运算符,执行了一个仿函数。函数运算符的重载很灵活,可以定义自己要传入的参数和返回值。

&&|| , 运算符不要重载

运算符本身有短路特性,重载后无法实现这些特性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值