首页 > 编程语言 >滴水逆向笔记系列-c++总结3-39.模板-40.引用_友元_运算符重载

滴水逆向笔记系列-c++总结3-39.模板-40.引用_友元_运算符重载

时间:2024-03-16 11:14:40浏览次数:27  
标签:友元 39 return int Number 运算符 Math operator highValue

第三十八课 c++6 模板

1.冒泡排序和折半查找

void Sort(int* arr,int nLength)						
{						
	int i;					
	int k;					
	for(i=0;i<nLength-1;i++)					
	{					
		for(k=0;k<nLength-1-i;k++)				
		{				
			if(arr[k]>arr[k+1])			
			{			
				int temp = arr[k];		
				arr[k] = arr[k+1];		
				arr[k+1] = temp;		
			}			
		}				
	}					
}						
int Find(int* arr,int nLength,int nElement)							
{							
	int nBegin = 0,nEnd = nLength-1,nIndex;						
	while(nBegin<=nEnd)						
	{						
		nIndex = (nBegin+nEnd)/2;//(nBegin+nEnd)>>1					
		if(nElement > arr[nIndex])					
		{					
			nBegin = nIndex+1;				
		}					
		else if(nElement < arr[nIndex])					
		{					
			nEnd = nIndex-1;				
		}					
		else					
		{					
			return nIndex;				
		}					
	}						
	return -1;						
}

2.模板的作用

先看看下面两种模板的使用

在函数中的使用

函数中传参什么T就代表什么类型

template<class T>				
void Sort(T arr,int nLength)				
{				
	int i;			
	int k;			
	for(i=0;i<nLength-1;i++)			
	{			
		for(k=0;k<nLength-1-i;k++)		
		{		
			if(arr[k]>arr[k+1])	
			{	
				int temp = arr[k];
				arr[k] = arr[k+1];
				arr[k+1] = temp;
			}	
		}		
	}			
}				

在类或结构体中的使用

类声明时<>表明什么类型就代表什么类型

template<class T,class M>				
struct Base				
{				
	T x;			
	T y;		
	M a;			
	M b;			
				
	T Max()			
	{			
		if(x>y)		
		{		
			return x;	
		}		
		else		
		{		
			return y;	
		}		
	}			
	M Min()			
	{			
		if(a<b)		
		{		
			return a;	
		}		
		else		
		{		
			return b;	
		}		
	}			
};				
int main(int argc, char* argv[])				
{				
	Base<int,char> base;			
	base.x = 10;			
	base.y = 20;			
	base.a = 1;			
	base.b = 2;			
				
	int x = base.Max();		
	int y = base.Min();			

	printf("%d %d\n",x,y);			
	return 0;			
}				

3.模板的反汇编

用不用模板从底层反汇编来看都是一样的
image.png

作业

image.png
1、函数模板传指针的情况

#include <stdio.h>
template <class T>
void Swap(T& x,T& y)
{
	T temp = x;
	x = y;
	y = temp;
}
int main()
{
	int x = 1;
	int y = 2;
	Swap(x,y);
	printf("%d , %d ",x,y);
}

3、可以看到还是调用了不同的函数地址,而且根据上面看到了用不用模板的反汇编代码都是一样的,所以可以看出模板的本质就是代码的复制,编译器帮我们对不同的类型多复制了几个函数
image.png

第三十九课 c++7 引用-友元- 运算符重载

1.引用

在函数参数传递时反汇编是没有区别的
image.png
看了这个我才能真理解引用就是变量别名的意思
而且初始化时一定要赋值

// 基本类型
int x = 1;
int& ref = x;
ref = 2;
printf("%d \n",ref);
 
// 类
Person p;
Person& ref = p;
ref.x = 10;
printf("%d \n",p.x);
 
// 指针类型
int****** x = (int******)1;
int******& ref = x;
ref = (int******)2;
printf("%d \n",x);
 
// 数组类型
int arr[] = {1,2,3};
int (&p)[3] = arr;
p[0] = 4;
printf("%d \n",arr[0]);

指针和引用

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);							
}		

int main(int argc, char* argv[])			
{			
	Base base(1,2);		
			
	PrintByRef(base,&base);	
	return 0;		
}			

可以看一下反汇编帮助理解一下,b1对象的值赋给了refb这个base的别名
image.png
有时候为了避免引用可以被修改,可以把引用声明为常量,不可修改
image.png

总结:

  1. 引用必须赋初始值,且只能指向一个变量,从一而终(专一)
  2. 对引用赋值,是对其指向的变量赋值,而不是修改引用本身的值;
  3. 对引用做运算,就是对其指向的变量做运算,而不是对引用本身做运算;
  4. 引用类型只能赋值一次,不能重新赋值
  5. 使用引用可以像指针那样去访问、修改对象的内容,但更加安全,但是不灵活

2.友元

当类内有两个私有成员,我们类外函数想直接访问时可以在类内声明这个类外函数是友元函数,那么友元函数就可以直接访问类内的私有成员

示例代码

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;			
}

总结:

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

  • 运算符重载的某些场合需要使用友元.
  • 两个类要共享数据的时候.

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

  • 成员函数有this指针,而友元函数没有this指针
  • 友元函数是不能被继承的,就像父亲的朋友未必是儿子的朋友

3.运算符重载

class Number		
{		
private:		
	int lowValue;	
	int highValue;	
public:		
	Number(int lowValue,int highValue);	
	void Print();	
	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();	
}		

作业

image.png
1、

#include <stdio.h>
class Math
{
private:
	int x ;
	int y ;
public:
	Math(int x,int y)
	{
		this->x = x;
		this->y = y;
	}
	friend Math& operator++(Math& m,int);
	friend bool operator==(Math& m, Math& t);
	friend void print(const Math& m);
};
Math& operator++(Math &m,int)
{
	m.x++;
	m.y++;
	return m;
}
bool operator==(Math& m, Math& t)
{
	if (m.x == t.x && m.y == t.y)
	{
		return true;
	}
	else
	{
		return false;
	}
}
void print(const Math& m)
{
	printf("%d %d\n", m.x, m.y);
}
int main()
{
	Math m(1, 2);
	Math m1(2,3);
	//m++;
	if (m == m1)
	{
		printf("相等\n");
	}
	else
	{
		printf("不相等\n");
	}
	print(m);
}

总结:

  • 友元函数去重载运算符应该传一个 Math 对象的引用作为参数,因为友元函数不像在类内声明的函数会自动传一个this指针
  • friend Math& operator++(Math& m,int);需要在传参时加一个占位参数int区分前缀自增还是后缀自增
  • Math&返回类型也使用引用,方便后置递增操作
  • void print(const Math& m)打印函数应该传静态的参数防止不小心被修改了

标签:友元,39,return,int,Number,运算符,Math,operator,highValue
From: https://www.cnblogs.com/xiaoxin07/p/18076811

相关文章

  • 实验 1 C语言开发实验环境和数据类型、运算符、表达式
     ......
  • module 'numpy' has no attribute 'bool'
    module'numpy'hasnoattribute'bool'问题:Traceback(mostrecentcalllast):File"/home/test.py",line138,in<module>inference(args,net,test_save_path)File"/home/test.py",line54,ininferenc......
  • 39. 组合总和c
    脑残了,参数传错了,debug了半天。/***Returnanarrayofarraysofsize*returnSize.*Thesizesofthearraysarereturnedas*returnColumnSizesarray.*Note:Bothreturnedarrayand*columnSizesarraymustbemalloced,assumecallercallsfree().*/int......
  • 代码随想录算法训练营第day46|139.单词拆分 、多重背包
    目录139.单词拆分多重背包 139.单词拆分力扣题目链接(opensnewwindow)给定一个非空字符串s和一个包含非空单词的列表wordDict,判定 s是否可以被空格拆分为一个或多个在字典中出现的单词。说明:拆分时可以重复使用字典中的单词。你可以假设字典中没有重复的单......
  • 03常见运算符
    1<!DOCTYPEhtml>2<htmllang="en">3<head>4<metacharset="UTF-8">5<metaname="viewport"content="width=device-width,initial-scale=1.0">6<title>Document......
  • Doremy's Drying Plan (Hard Version)
    我们先来看看简单版本的想法,非常具有启发性大致的思路见这篇文章下面是对这篇文章具体操作的阐释我们先将所有区间按照左端点单调递增排序,并统计每一个区间中\(c_i=1\)的个数(这个直接用前缀和就好了,设\(sum[i][j]\)表示前\(i\)个数中\(c_k=j\)的个数),枚举其中一个区间(设为\([l,r......
  • 代码随想录算法训练营第四十六天| 139.单词拆分 多重背包 背包问题总结篇!
    单词拆分 题目链接:139.单词拆分-力扣(LeetCode)思路:竟然真能转化为背包问题。classSolution{public:boolwordBreak(strings,vector<string>&wordDict){unordered_set<string>t(wordDict.begin(),wordDict.end());vector<bool>dp(s.size()+......
  • Doremy's Connecting Plan
    这道题目。。哎首先,我们对两个连通块进行连边的时候,肯定是选择编号最小的点进行连边,所以下文的\(i,j\)都指代编号最小的\(i,j\)然后我们就没有其他思路了。。但其实样例一的解释给了我们一种猜想:最终的图一定可以长成以\(1\)号点为中心的菊花图要达到这一点,我们肯定是尝试构造......
  • 实验1 c语言开发环境使用和数据类型、运算符、表达式
    task1`#include<stdio.h>intmain(){printf("o\n");printf("\n");printf("II\n");printf("o\n");printf("<H>\n");printf("II\n");return0;}``#include<stdio......
  • MySQL之运算符篇
    1.算术运算符算术运算符主要用于数学运算,其可以连接运算符前后的两个数值或表达式,对数值或表达式进行加(+)、减(-)、乘(*)、除(/)和取模(%)运算。1.1 加法与减法运算符由运算结果可以得出如下结论:一个整数类型的值对整数进行加法和减法操作,结果还是一个整数;一个整数类型的值......