c++_note_4_运算符重载

4.运算符重载

运算符重载的两种方法:

  • 全局函数
  • 成员函数

基础的有一元、二元、加减、++和–。

运算符原有意义没有失去,只是定义了某类的新运算符。
运算符重载的本质是函数调用。

运算符函数可以重载为成员函数或友元函数,区别是有无this。
c3 = operator+(c1,c2);
c3 = c1.operator+(c2);

一元运算符相对二元运算符的重载更复杂.

istreamostream是c++的预定义流类,它们的左移右移操作符,左侧运算量是 cin或cout 而不是对象本身,我们只能用友元函数重载。
cin/coutistream/ostream的对象.

friend ostream& operator<<(ostream &out, Complex &c);
cout<<c1<<endl;
左右移的运行顺序是从左到右的,所以上面两行就相当于
operator<<(cout,c1).operator<<(endl);
所以返回类型是ostream&

复数类示例

#include<iostream>
using namespace std;

class Complex{
public:
	Complex(){
		this->x = 0;
		this->y = 0;
	}

	Complex(int x, int y){
		this->x = x;
		this->y = y;
	}
	Complex(const Complex &c){
		cout<<"copy"<<endl;
	}

	void print(){
		if(y < 0)
			cout<<x<<y<<"i"<<endl;
		else
			cout<<x<<"+"<<y<<"i"<<endl;
	}
	
	Complex operator+(Complex &c2){
		Complex c(this->x + c2.x, this->y + c2.y);
		return c;
	}
	friend Complex operator-(Complex &c1 , Complex &c2);
	
	
	//前置++,-- 
	friend Complex& operator++(Complex &c);
	Complex& operator--(){
		this->x--;
		this->y--;
		return *this;
	}
	
	
	//后置++,-- 
	friend Complex operator++(Complex &c , int);
	Complex operator--(int){
		Complex tmp = *this;  //copy
		this->x--;
		this->y--;
		return tmp;
	}
	
	friend ostream& operator<<(ostream &out, Complex &c);
	
private:
	int x,y;
};

/*
Complex operator+(Complex &c1 , Complex &c2){
	Complex c(c1.getX() + c2.getX(), c1.getY() + c2.getY());
	return c;
}
*/
Complex operator-(Complex &c1 , Complex &c2){
	Complex c(c1.x - c2.x, c1.y - c2.y);
	return c;
}

Complex& operator++(Complex &c){  //前置++ 
	c.x++;
	c.y++;
	return c;
}

Complex operator++(Complex &c , int){  //后置++ 
	Complex tmp = c;  //copy
	c.x++;
	c.y++;
	return tmp;
}

ostream& operator<<(ostream &out, Complex &c){
	if(c.y < 0)
		out<<c.x<<c.y<<"i"<<endl;
	else
		out<<c.x<<"+"<<c.y<<"i"<<endl;
	return out;
} 

int main(int argc, char *argv[])
{
	Complex c1(1,2),c2(3,4);
	Complex c3;
	
	cout<<"	c3 = operator+(c1,c2)"<<endl; 
	//c3 = operator+(c1,c2);
	//c3.print();
	cout<<endl;  
	
	cout<<"	c3 = c1 + c2"<<endl; 
	c3 = c1 + c2;
	c3.print(); 
	cout<<endl; 

	
	cout<<"	Complex c4 = operator-(c1,c2)"<<endl; 
	Complex c4 = operator-(c1,c2);
	c4.print();
	cout<<endl; 
	
	cout<<"	c4 = c1 - c2"<<endl; 
	c4 = c1 - c2;
 	c4.print();
	cout<<endl; 
	
	cout<<"	operator++(c1)"<<endl; 
	operator++(c1);
	c1.print();
	cout<<"	++c1"<<endl; 
	++c1;
 	c1.print();
	cout<<endl; 
	
	cout<<"	--c1"<<endl; 
	--c1;
 	c1.print();
	cout<<endl; 
	
	cout<<"	c1++;"<<endl; 
	c1++;
 	c1.print();
	cout<<endl; 
	
	cout<<"	c1--;"<<endl; 
	c1--;
 	c1.print();
	cout<<endl; 
	
	cout<<"	operator<<(cout,c1).operator<<(endl); "<<endl;
	//cout.operator<<(cout,c1).operator<<endl;
	cout<<"	cout<<c1<<endl; "<<endl;
	cout<<c1<<endl; 
	
	cin.get();
	return 0;
}

成员函数重载

4种不能用友元函数重载的操作符:
= () [] ->

等号重载注意:

  1. 释放旧内存
  2. 返回一个引用

等号运算顺序是从右到左

()[]等都是二元运算符,只能用成员函数重载,不能用友元函数重载。

/*
	等号重载
*/
#include<iostream>
#include<string>
using namespace std;

class Person{
public:
	Person(const char* name, int age){
		this->name = (char*)malloc(strlen(name) + 1);
		strcpy(this->name, name);
		this->age = age;
	}
	Person& operator=(Person& p){
		char *tmpP;
		if(this->name != NULL){
			//delete[] this->name;
			tmpP = this->name;
			this->name = NULL;
		}
		this->name = (char*)malloc(strlen(p.name) + 1);
		strcpy(this->name, p.name);
		free(tmpP);
		tmpP = NULL;
		this->age = p.age;
		return *this;
	}
	void printAddr(){
		printf("%p\n",this->name);
	}
private:
	char *name;
	int age;
};

int main(int argc, char *argv[])
{
	Person p1("foo",1),p2("bar",2);
	Person p3("abc",3);
	
	p1.printAddr();
	p2.printAddr();
	p3.printAddr();
	
	p1 = p2 = p3;
	
	cout<<endl;
	p1.printAddr();
	p2.printAddr();
	p3.printAddr();
	cin.get();
	return 0;
}

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

class Person{
public:
	Person(int i){
		this->name = new char[i];
	}
	Person(const Person& p){
		cout<<"copy"<<endl;
	}
	void setName(const char* name){
		if(this->name != NULL){
			free(this->name);
			this->name = NULL;
		}
		this->name = (char*)malloc(sizeof(strlen(name)) + 1);
		strcpy(this->name,name);
	}
	int getNameLen(){
		return strlen(this->name);
	}
	
	char& operator[](int i);
	Person& operator=(Person& p);
	bool operator==(Person &p);
	bool operator!=(Person &p);
private:
	char *name;
};

// [] 重载
char& Person::operator[](int i){
	return this->name[i];
}

Person& Person::operator=(Person& p){
	if(this->name != NULL){
			free(this->name);
			this->name = NULL;
	}
	this->name = (char*)malloc(sizeof(strlen(p.name)) + 1);
	strcpy(this->name,p.name);
	return *this;
}

bool Person::operator==(Person &p){
	return !strcmp(this->name,p.name);
}
bool Person::operator!=(Person &p){
	return !(*this == p);
	//return strcmp(this->name,p.name);
}

int main(int argc, char *argv[])
{
	Person p1(10);
	p1.setName("foobar");
	
	for(int i = 0 ; i < p1.getNameLen() ; i++){
		printf("%c",p1[i]);
	}
	for(int i = 0 ; i < p1.getNameLen() ; i++){
		printf("%c",p1.operator[](i));
	}
	cout<<endl;
	
	Person p2 = p1;  //disiplay "copy"
	p2.operator=(p1);
	p2 = p1;
	for(int i = 0 ; i < p2.getNameLen() ; i++){
		printf("%c",p2[i]);
	}
	cout<<endl;
	
	cout<<endl;
	if(p1 == p2) cout<<"p1==p2"<<endl;
	if(p1.operator==(p2)) cout<<"p1==p2"<<endl;
	p2.setName("abcdef");
	if(p1 != p2) cout<<"p1!=p2"<<endl;
	if(p1.operator!=(p2)) cout<<"p1!=p2"<<endl;

	
	cin.get();
	return 0;
}


对象带括号,可能是构造,也可能是重载。

#include<iostream>
using namespace std;

class MyClass{
private:

public:
	int operator()(int a, int b){
		return a+b;
	}
};

int main(int argc, char *argv[])
{
	MyClass c;
	int a = c(1,2);
	cout<<a<<endl;
	cin.get();
	return 0;
}

关于&&和||

不要重载&&||
它们有短路规则,从左到右执行,重载的话会破坏这个规则。
例如:obj1 && (obj1 + obj2)
它会先执行加号。
即使这样写
(obj1 + obj2) && obj1
如果左边为假,还是会执行&&,破坏了短路规则。

#include<iostream>
using namespace std;

class T{
public:
	int i; 
	
	T(int i){
		this->i = i;
	}
	T operator+(const T &o){
		T t(0);
		t.i = this->i + o.i;
		cout<<"exec +"<<endl;
		return t;
	}
	bool operator&&(const T& o){
		cout<<"exec && func."<<endl;
		return this->i && o.i;
	}
};

int main(int argc, char *argv[])
{
	T t1(0),t2(1);
	if( t1 && (t1 + t2) ){
		cout<<"t1 && (t1 + t2):true"<<endl;
	}
	t2.i= 0;
	if( (t1 + t2) && t1 ){
		cout<<"(t1 + t2) && t1:true"<<endl;
	}
	cin.get();
	return 0;
}

MyString类示例

/*
	MyString.h
*/
#pragma once
#include<iostream>
using namespace std;
class MyString{
private:
	int 	len;
	char 	*p;
public:
	MyString();
	MyString(const char *s);
	MyString(int n);
	MyString(const MyString& s);
	~MyString();
	char* getP() const;
	
	char& operator[](int index);
	MyString& operator=(const char*s);
	MyString& operator=(const MyString &s);
	
	friend ostream& operator<<(ostream &out, MyString &s);
	friend istream& operator>>(istream &out, MyString &s);
	
	
	bool operator==(const char* s) const;
	bool operator==(const MyString& s) const;
	bool operator!=(const char* s) const;
	bool operator!=(const MyString& s) const;
	
	bool operator<(const char* s);
	bool operator<(const MyString& s);
	bool operator>(const char* s);
	bool operator>(const MyString& s);
	
	int getL() const;
	void print();
};

/*
	MyString.cpp
*/
#include "MyString.h"

MyString::MyString(){
	len = 0;
	p = new char[len+1];
	strcpy(p,"");
} 
MyString::MyString(const char *s){
	if( s == NULL){
		len = 0;
		p = new char[len+1];
		strcpy(p,"");
	}
	else{
		len = strlen(s);
		p = new char[len+1];
		strcpy(p,s);
	}
	
}
MyString::MyString(int n){
	if(n == 0){
		len = 0;
		p = new char[len + 1];
		strcpy(p,"");
	}
	else{
		len = n;
		p = new char[len + 1];
		memset(p,0,len);
	}
}
char* MyString::getP() const{
	return this->p;
}
int MyString::getL() const{
	return this->len;
}
MyString::MyString(const MyString& s){
	if(p != NULL){
		delete[] p;
		p = NULL;
	}
	len = s.getL();
	p = new char[len+1];
	strcpy(p,s.getP());
	
}
MyString::~MyString(){
	if(p != NULL){
		delete[] p;
		p = NULL;
		len = 0;
	}
}


char& MyString::operator[](int index){
	return p[index];
} 
MyString& MyString::operator=(const char*s){
	if( p !=  NULL ){
		delete[] p;
		len = 0;
	}
	if( s == NULL ){
		len = 0;
		p = new char[len+1];
		strcpy(p,"");
	}
	else{
		len = strlen(s);
		p = new char[len+1];
		strcpy(p,s);
	}
	return *this;
}
MyString& MyString::operator=(const MyString &s){
	if( p !=  NULL ){
		delete[] p;
		len = 0;
	}

	len = s.getL();
	p = new char[len+1];
	strcpy(p,s.getP());
	return *this;
}

ostream& operator<<(std::ostream &out, MyString &s){
	out<<s.getP();
	return out;
}
bool MyString::operator==(const char* s) const{
	if(s == NULL){
		if(len == 0){
			return true;
		}
		else
		{
			return false;
		}
	}
	else{
		if(len == strlen(s)){
			return !strcmp(p,s);
		}
		else
		{
			return false;
		}
	}	
}

bool MyString::operator!=(const char* s) const{
	return !(*this == s);
}
bool MyString::operator==(const MyString& s) const{
	if(len != s.getL()){
		return false;
	} 
	else{
		return !strcmp(p,s.getP());
	}
}

bool MyString::operator!=(const MyString& s) const{
	if(len != s.getL()){
		return true;
	} 
	else{
		return p != s.getP();
	}
}
bool MyString::operator<(const char* s){
	int ret = strcmp(p,s);
	if(ret < 0){
		return true;
	}
	else{
		return false;
	}
}
bool MyString::operator>(const char* s){
	int ret = strcmp(p,s);
	if(ret > 0){
		return true;
	}
	else{
		return false;
	}
}
bool MyString::operator<(const MyString& s){
	return p<s.getP();
}

bool MyString::operator>(const MyString& s){
	return p>s.getP();
}
	

istream& operator>>(istream &out, MyString &s){
	cin>>s.getP();
	return out;
}
	
	
void MyString::print(){
	cout<<p<<endl;
}

/*
	main.cpp
*/

#include<cstdlib>
#include<cstring>
#include "MyString.h"

using namespace std;
int main(int argc, char *argv[])
{	
	MyString s1;
	MyString s2("abc");
	MyString s3 = s2;
	s1.print();
	s2.print();
	s3.print();
	
	s3[0] = 'b';
	MyString s4 = "def";
	s3.print();
	s4.print(); 
	
	cout<<s4<<endl;
	
	MyString s5 = s4;
	if(s5 == s4){
		cout<<"s5==s4"<<endl;
	}
	else{
		cout<<"s5!=s4"<<endl;
	}
	if(s5 != s3){
		cout<<"s5!=s3"<<endl;
	}
	else{
		cout<<"s5==s3"<<endl;
	}
	
	if(s1 == NULL){
		cout<<"s1 == NULL"<<endl;
	}
	else{
		cout<<"s1 != NULL"<<endl;
	}
	
	cout<<(s5<"a")<<endl;
	cout<<(s5>"a")<<endl;
	cout<<(s5<s2)<<endl;
	//cout<<(s5<NULL)<<endl;
	
	
	MyString s6(10);
	cin>>s6;
	cout<<s6<<endl;
	
	
	cin.get();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值