CPPDay04运算符重载(友缘,友元)

 

目录

 1.为什么要重载运算符:

2.运算符的本质:函数

3.如何重载运算符

4.友缘,友元

5.输出运算符重载

6. 一般运算符重载的规范:   

7. 哪些运算符不能重载   

8.运算符重载分类   

9.运算符重载需知:


1.为什么要重载运算符:

 我们希望自己抽象出来的类也可以使用运算符去操作。

2.运算符的本质:函数

3.如何重载运算符

    函数名:
      operator 运算符名
    参数列表:
      双目运算符    两个参数
      单目运算符    一个参数
      三目运算符不能重载
      如果运算符重载函数是类的成员函数,那么 参数列表少一个。
    返回值:
      所有运算符重载函数,都有且只有一个返回值。
    1.18     2.987
    18 + 987  ==

4.友缘,友元

 有类A,A的成员函数可以访问私有成员变量。如果有一个函数func不是A的成员函数,这个函数中能否访问类A的成员变量?不能。如果声明函数func是类A的友元函数,那么函数func中可以访问A类对象的私有成员。

5.输出运算符重载

 cout << 某个对象

6. 一般运算符重载的规范:
   

双目运算符  一般  重载为友元
    单目运算符  一般  重载为成员

7. 哪些运算符不能重载
   

?:
    ::
    . ->
    &
    数组的[]     

8.运算符重载分类

  1. 算术运算符: + - * / % + -
  2.  输入输出运算符:>>   <<
  3.  位运算符:
  4.  自运算符:++ ++ -- --
  5.  关系运算符: >   <   == !=   !
  6.  逻辑运算符:
  7.  * 解引用:
  8.   泛型  
  9. 赋值运算符重载:
    1. 编译器会自动帮我们写。
    2. 只能重载为成员
  10. 动态内存分配重载:new  delete  new[] delete[]

9.运算符重载需知:


      1.重载后的运算符功能应该和本来的相同
      2.不能自定义
      3.不能改变运算符优先级
    
    

// 算术运算符重载.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;
//小数类
class xiaoshu{
	int zheng;
	int xiao;
public:
	xiaoshu(){ cout << "构造器" << endl;  zheng = xiao = 0; }
	xiaoshu(int z, int x) :zheng(z), xiao(x){ cout << "有参构造器" << endl; }

	xiaoshu operator+(const xiaoshu& xs);//const;//"operator+"这个整体就是函数名,该成员函数是小数类的对象在调用,xs1+xs2其实是xs1.+xs2省略了点,所以本来需要两个形参,现在只要一个就够了
   //如果形参是 xiaoshu 类型,那么在传参的时候,就会临时构造出一个 xiaoshu类型的对象来储存实参的副本,增加了空间复杂度。
   //并且要在xiaoshu &xs前加上const ,这样就不能给xs赋值,来改变xs和它的别名的值了,保护xs2
   //在函数后加上const 表名该函数为const成员函数,不能在函数内修改该类成员变量的值,保护xs1
   //该函数的返回值是小数类型的一个临时对象,且加上const 表示该临时对象不能修改。(不加const也没有关系)
private:
	int		_jia(int a, int b);
	int		_getWeiShu(int a););//求一个整数有多少个位的函数
//    bool _isJinWei()//判断是否进位
public:
	void setZheng(int z){ this->zheng = z; }
	void setXiao(int x){ this->xiao = x; }
};

//求一个整数有多少个位
int xiaoshu::_getWeiShu(int a){
	int count = 0;
	while (a){
		a /= 10;
		count++;
	}
	return count;
}

int xiaoshu::_jia(int a, int b){
	//最高位相加
	int aWeiShu = _getWeiShu(a);
	int bWeiShu = _getWeiShu(b);

	if (aWeiShu == bWeiShu) return a + b;
	if (aWeiShu > bWeiShu){
		for (int i = 0; i < (aWeiShu - bWeiShu); i++)
			b *= 10;
		return a + b;
	}

	for (int i = 0; i < (bWeiShu - aWeiShu); i++)
		a *= 10;
	return a + b;
}

xiaoshu xiaoshu::operator+(const xiaoshu& xs){
	xiaoshu temp; //temp.xiao=this->xiao +xs.xiao;不能直接加,必须判断小数的位数,比如1.17+1.189不鞥17+189,必须先判断位数
//	temp.xiao = this->xiao + xs.xiao;
	temp.setXiao( _jia(xiao, xs.xiao) );
	temp.setZheng(this->zheng + xs.zheng );
	return temp;
}


int _tmain(int argc, _TCHAR* argv[])
{
	xiaoshu xs1(2,345), xs2(2,3);

	xiaoshu xs3 = xs1 + xs2;

	while (1);
	return 0;
}
// 输出运算符重载.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <iostream> // istream:输入流类  对应cin这个对象   ostream:输出流类 对应cout这个类 
using namespace std;

class Fenshu{
	int fenzi;
	int fenmu;
public:
	Fenshu(){
		fenzi = 0;
		fenmu = 1;
		cout << "无参构造" << endl;
	}
	Fenshu(int fenzi, int fenmu) :fenzi(fenzi), fenmu(fenmu){
		cout << "有参构造" << endl;
	}
	friend ostream& operator<<(ostream& o, const Fenshu& fs);
	friend istream& operator>>(istream& i, Fenshu& fs);
};

//重载输出运算符
ostream& operator<<(ostream& o,const Fenshu& fs){//该函数的左值是cout,所以第一个参数应该是ostream类对象的引用,右值是fs,所以第二个参数就是Fenshu类对象的引用,两个参数的位置不可替换
	//operator<<函数的返回值是 ostream输出类的对象的引用,也就是cout这个输出类对象。

	return o << fs.fenzi << " / " << fs.fenmu;
}
/*
cout是个流对象,或者说是ostream这个类的对象,该类内部有输出缓冲区,当执行cout << x的时候,其实就是调用了ostream的operator<< 方法,该方法是对<<运算符的重载,该方法的参数即是x。
operator<<方法返回ostream类的引用,即该类对象自身,所以cout << x 语句可以做左值,即支持连续调用: cout << x << y.....
x变量内容拷贝到缓冲区中,ostream内部会根据某种缓冲机制(全缓冲,行缓冲,无缓冲)将缓冲区的内容输出到屏幕终端。

*/
//重载输入运算符
istream& operator>>(istream& i,Fenshu& fs){
	char c;
	return i >> fs.fenzi >> c >> fs.fenmu;
}

int main(){
	Fenshu fs1(3, 4);
	cout << fs1 << endl;


	cin >> fs1;


	cout << fs1 << endl;

	cout << 1 << 3 << 4 << 5;


	while (1);
	return 0;
}


#if 0
class A{
	int a;
public:
	void setA(int a){ this->a = a; }
	//声明函数func是本类的友元函数
	friend void func(A& a);
};

void func(A& a){
	cout << a.a << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	A aa;
	aa.

	while (1);
	return 0;
}

#endif
// 自运算符重载.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream> // istream:输入流对象  cin   ostream:输出流对象 cout 
using namespace std;
class Fenshu{
	int fenzi;
	int fenmu;
public:
	Fenshu(){
		fenzi = 0;
		fenmu = 1;
		cout << "无参构造" << endl;
	}
	Fenshu(int fenzi, int fenmu) :fenzi(fenzi), fenmu(fenmu){
		cout << "有参构造" << endl;
	}
	friend ostream& operator<<(ostream& o, const Fenshu& fs);
	friend istream& operator>>(istream& i, Fenshu& fs);

	//后自增   n++		
	Fenshu operator++(int);
	//前自增   ++n
	Fenshu operator++();


	//关系运算符重载
	friend bool operator>(const Fenshu& fs1, const Fenshu& fs2);

	//赋值运算符重载
	Fenshu& operator=(const Fenshu& fs2);
};

Fenshu& Fenshu::operator = (const Fenshu& fs2){
	cout << "赋值运算符重载" << endl;
	this->fenzi = fs2.fenzi;
	this->fenmu = fs2.fenmu;
	return *this;
}

bool operator>(const Fenshu& fs1, const Fenshu& fs2){
	int fz1 = fs1.fenzi * fs2.fenmu;
	int fz2 = fs2.fenzi * fs1.fenmu;
	return (fz1 > fz2);
}


//后自增   n++		先参与运算,再自增
Fenshu Fenshu::operator++(int){
	Fenshu fs = *this;
	fenzi = fenzi + fenmu;   
	return fs;
}
//前自增   ++n      先自增,再参与运算
Fenshu Fenshu::operator++(){
	fenzi = fenzi + fenmu;
	return *this;
}


//重载输出运算符
ostream& operator<<(ostream& o, const Fenshu& fs){
	return o << fs.fenzi << " / " << fs.fenmu;
}
//重载输入运算符
istream& operator>>(istream& i, Fenshu& fs){
	char c;
	return i >> fs.fenzi >> c >> fs.fenmu;
}


int _tmain(int argc, _TCHAR* argv[])
{
	Fenshu fs(1, 2);
	Fenshu fs1(2, 6);
	Fenshu fs2(3, 9);

	fs = fs1 = fs2;


	cout << (fs > fs1) << endl;

	cout << fs << endl;

	cout << fs++ << endl;

	cout << fs << endl;
	cout << ++fs << endl;



	while (1);
	return 0;
}


    

// new运算符重载.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <string.h>
#include <stdlib.h>
//内存泄漏:  申请了堆内存却没有及时释放
//越界:数组越界  访问了数组之外的内存段

class MyString{
	char* pBuff;
	size_t size;
public:
	MyString(){ pBuff = NULL; size = 0; }
	MyString(char* str){
		int len = strlen(str);
		pBuff = new char[len + 1];
		memcpy(pBuff, str, sizeof(char)* (len + 1) );
		size = len;
	}

	void* operator new(size_t len);
	void* operator new[](size_t len);
	void operator delete[](void* p, size_t len);
	void operator delete(void* p,size_t len);


	~MyString(){
		if (pBuff){
			delete[] pBuff;
		}
		pBuff = NULL;
		size = 0;
	}
};

void MyString::operator delete(void* p,size_t len){
	printf("释放%d字节内存段!\n",len);
	free(p);
}
void* MyString::operator new(size_t len){
	printf("开辟%d字节内存段!\n", len);
	return malloc(len);
}

void MyString::operator delete[](void* p, size_t len){
	printf("释放%d字节内存段!\n", len);
	printf("使用的是中括号\n");
	free(p);
}
void* MyString::operator new[](size_t len){
	printf("开辟%d字节内存段!\n", len);
	printf("使用的是中括号\n");
	return malloc(len);
}


int _tmain(int argc, _TCHAR* argv[])
{
	MyString* pStr = new MyString("hello");
	MyString* pStr2 = new MyString[5] ;

	delete[] pStr2;

	delete pStr;
	while (1);
	return 0;
}


    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
   

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值