引用-友元-运算符重载

引用

引用类型不能更改

struct Base								
{								
	int x;							
	int y;							
	Base(int x,int y)							
	{							
		this->x = x;						
		this->y = y;						
	}							
};								
void PrintByPoint(Base* pb)								
{								
	printf("%d  %d\n",pb->x,pb->y);							
								
	pb = (Base*)0x123456;							
								
	//为所欲为...							
}								
void PrintByRef(Base& refb,Base* pb)								
{								
	printf("%d  %d\n",refb.x,refb.y);							
	Base b1(21,31);							
	//&refb = b1; //引用不能重新赋值							
	refb = b1;  //这个不是重新赋值,这个是把b1的值赋给refb代表的对象							
	printf("%d  %d\n",pb->x,pb->y);							
}								

​ 为了避免出现这种情况,可以将refb声明为常量,不可修改:

	void PrintByRef(const Base& refb)					
	{					
		printf("%d  %d\n",refb.x,refb.y);				
		Base b1(21,31);				
		//&refb = b1; //引用不能重新赋值				
		//refb = b1;  //不允许	,因为定义成了常量类型			
	}					

与指针的反汇编区别

void demo(int& arg)

{
 arg=1;//与指针的差别 前面可以不用加*  给指针指向的地址赋值.相当于给main那里的a赋值
}
int main(int argc,char* argv[])
{
int a=10;
 demo(a);//在c++中  demo的参数a有可能是int 类型 有可能会是int类型的引用  这里直接传变量
return 0;
}
//在反汇编中 上面的反汇编代码同下面的指针类型没差别:
void demo(int* arg)
{
 *arg=1;
}
int main(int argc,char* argv[])
{
int a=10;
demo(&a);//在c++中  demo的参数a有可能是int 类型 有可能会是int类型的引用 这里需要传变量地址
return 0;
}

唯一的区别就是指针传参,指针可以指向别的地方(乱指会出错).

而引用的话 编译器不允许再指向别的地方

总结

  1. 引用和指针在底层汇编阶段没有任何区别,都是地址传递。
  2. 不同:指针可能出现地址乱指的问题,而引用则不会,改变引用的值实际上是改变变量地址上的值,而不是变量的地址。
  3. 引用是C++中特有类型。
  4. 引用类型只能赋值一次,不能重新赋值。
  5. 引用只是变量的一个别名。
  6. 引用可以理解成是编译器维护的一个指针,但并不占用空间。
  7. 使用引用可以像指针那样去访问、修改对象的内容,但更安全。

友元函数

class Person				
{				
private:				
	int x;			
	int y;			
public:				
	Person(int x,int y)			
	{			
		this->x = x;		
		this->y = y;		
	}			
	//声明友元函数			
	//friend void Print(const  Person& refPer);			
};				
void Print(const Person& refPer)				
{				
	printf("%d\n",refPer.x);			
	printf("%d\n",refPer.y);			
}				
int main(int argc, char* argv[])				
{				
	Person p(1,2);			
				
	Print(p);			
				
	return 0;			
}				

还有友元类,本质都是在需要使用的类里面声明外部某函数 某类是朋友,可以调用本类中的私有成员

总结

什么情况下需要友元函数:

(1) 运算符重载的某些场合需要使用友元.

(2) 两个类要共享数据的时候.

友元函数和类的成员函数的区别

(1) 成员函数有this指针,而友元函数没有this指针

(2) 友元函数是不能被继承的,就像父亲的朋友未必是儿子的朋友

运算符重载

			
	class Number		
	{		
	private:		
		int lowValue;	
		int highValue;	
	public:		
		Number(int lowValue,int highValue);	
		void Print();	
 //写运算符重载一定要注意,因为它本身也是一个函数,是函数就有返回值.它的这个运算返回值必须是它自己的类型   Int i; i++  i加完还是int  所以 这里运算符重载的子程序运算完后 返回值类型应该还是demo
		Number operator++();	
		Number operator--();	
		Number operator+(const Number& p);	
		Number operator-(const Number& p);	
		Number operator*(const Number& p);	
		Number operator/(const Number& p);	
         //但是如果重载的是大于这类的运算符,返回值类型应该是逻辑类型
		bool operator>(const Number& p);	
		bool operator<(const Number& p);	
		bool operator==(const Number& p);	
	};		
	Number::Number(int lowValue,int highValue)		
	{		
		this->lowValue = lowValue;	
		this->highValue = highValue;	
	}		
	void Number::Print()		
	{		
		printf("%d\n",lowValue);	
		printf("%d\n",highValue);	
	}		
	Number Number::operator++()		
	{		
		lowValue++;	
		highValue++;	
		return *this;	
	}		
	Number Number::operator--()		
	{		
		lowValue--;	
		highValue--;	
		return *this;	
	}		
	Number Number::operator+(const Number& p)		
	{		
		this->highValue = this->highValue + p.highValue;	
		this->lowValue = this->lowValue + p.lowValue;	
		return *this;	
	}		
	Number Number::operator-(const Number& p)		
	{		
		this->highValue = this->highValue - p.highValue;	
		this->lowValue = this->lowValue - p.lowValue;	
		return *this;	
	}		
	Number Number::operator*(const Number& p)		
	{		
		this->highValue = this->highValue * p.highValue;	
		this->lowValue = this->lowValue * p.lowValue;	
		return *this;	
	}		
	Number Number::operator/(const Number& p)		
	{		
		this->highValue = this->highValue / p.highValue;	
		this->lowValue = this->lowValue / p.lowValue;	
		return *this;	
	}		
	bool Number::operator>(const Number& p)		
	{		
		if(this->highValue > p.highValue)	
		{	
			return true;
		}	
		return false;	
	}		
	bool Number::operator<(const Number& p)		
	{		
		if(this->highValue < p.highValue)	
		{	
			return true;
		}	
		return false;	
	}		
	bool Number::operator==(const Number& p)		
	{		
		if(this->highValue == p.highValue)	
		{	
			return true;
		}	
		return false;	
	}		
	void Test()		
	{		
		Number p(1,2),p2(3,4);	
		p++;	
		p.Print();	
		p--;	
		p.Print();	
			
		p = p+p2;	
		p.Print();	
			
	}		
	int main(int argc, char* argv[])		
	{		
		Test();	
			
			
			
		return 0;	
	}		
			

总结

  1. 运算符重载就是函数替换
  2. . :: ?: sizeof # 不能重载
  3. 除了在结构体内部定义,使用友元函数也可以实现(+±-这种需要用到this指针的不适用)
  4. 有些情况下,一定要用到友元函数…

本节练习:

1、定义一个类,使用友元函数实现:+、-、*、/、>、<、>=、<=
等运算符重载(什么情况下,一定要用友元函数?).

运算符重载通常可以用成员函数或者非成员函数(友元函数)来实现。使用哪种方法取决于操作数和操作符的类型。

在某些情况下,如果我们需要访问类的私有成员变量或函数,而这些变量或函数又不是该类的成员函数,则需要使用友元函数来重载运算符。因为只有友元函数能够访问类的私有成员。

具体来说,以下情况下必须使用友元函数来重载运算符:

  1. 当操作符的左操作数是一个自定义类型的对象,右操作数不是自定义类型的对象时,必须使用友元函数。
  2. 当我们需要访问私有成员变量时,必须使用友元函数。

例如,如果我们想要重载“+”运算符来实现两个自定义类型对象的相加操作,而其中一个操作数是 int 类型,则需要使用友元函数。因为 int 类型不是我们自定义的类型,不能访问我们类中的私有成员变量和函数。

#include"c++test.h"
#include<stdio.h>
#include<Windows.h>
#include<stdio.h>
#include<Windows.h>

class Sub; // 提前声明 Sub 类

class Base
{
private:
    int x;
    int y;
public:
    Base(int w, int z)
    {
        this->x = w;
        this->y = z;
    }
    bool operator==(const Base& p) const; // 修改 operator== 函数的参数、返回值和修饰符
    int operator+(const Sub& p); // 添加 operator+ 函数
};

class Sub
{
private:
    int a;
    int b;
public:
    Sub(int x, int y)
    {
        this->a = x;
        this->b = y;
    }
    friend int Base::operator+(const Sub& p); // 修改 operator+ 函数的参数和返回值
};

bool Base::operator==(const Base& p) const // 修改 operator== 函数的参数、返回值和修饰符
{
    if (this->x == p.x && this->y == p.y)
        return true;
    else
        return false;
}

int Base::operator+(const Sub& p) // 添加 operator+ 函数
{
    return this->x + p.a; // 将 pb 的 x 值加上 pc 的 a 值并返回
}

int main(int argc, char* argv[])
{
    Base pb(1, 2);
    Sub pc(1, 2);

    int k = 1;
    int sum = pb + pc; // 先将 pb 和 pc 相加
    printf("%d", sum); // 再打印出结果

    return 0;
}

是用友元函数进行函数重载

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值