网站建设资讯

NEWS

网站建设资讯

C++基础4类const函数转全局函数返回*this数组类。友元函数类操作符重载

1)

专注于为中小企业提供成都网站建设、网站设计服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业怒江州免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了上千企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。

请问类中函数 const修饰的谁

把类中的成员函数 转换成全局函数

成员函数返回*this

2)

自定义数组类封装 申明 与实现分开写 具有以下函数

void arr_set(int n,int value);

int  arr_get(int n);

int  arr_len()

3)

为什么会有友元函数

友元类:


4)

运算符重载

可以进行运算符重载的符

【二元操作符】 + - 

全局函数的运算符重载,private成员变量

成员函数的运算符重载,private成员变量

【一元运算符】

成员函数,全局函数

前置++   后置++ 

前置--   后置--

有元函数的正真使用场景:

返回引用类型,链式输出对象的信息

5)

【难点】运算符重载提高 

等号=

中括号[],当左值,当右值

相等符号 ==

不等于 !=

6)作业:封装一个字符类,使用 << ,>>,!= ,==,=,

 

附:运算符结合方向:

1,请问类中函数 const修饰的谁?

chunli@Linux:~/c++$ cat main.cpp 
#include 
#include 
using namespace std;

class A
{
public:
	//const的三种写法
	//const void fun(int a,int b)
	//void const fun(int a,int b)
	//void fun(int a,int b) const
	void fun(int a,int b) const
	{
		a = 100;	//const 修饰的不是a
		//this->a = 200;	//编译提示:‘A::a’ in read-only object
	}
private:
	int  a;
	int  b;
};

int main()
{
	A a1;
	return 0;
}

答案:

const的三种写法修饰的是this指针

const void fun(int a,int b)

void const fun(int a,int b)

void fun(int a,int b) const

this指针所指向的内存空间不能被修改

相当于 void fun(const A *this,int a,int b)

修改this指针本身的值,编译也不通过

把类中的成员函数 转换成全局函数

chunli@Linux:~/c++$ cat main.cpp 
#include 
#include 
using namespace std;

class A
{
public:
	void fun()
	{
		cout << "a="<a<<" b="<b<< "  in fun"<a = a;
		this->b = b;
		cout << "a="<a<<" b="<b<<"  in init  \n";
	}
	A add(A &a)
	{
		A t(this->a + a.a,this->b + a.b);
		return t;
	}
	A (const  A &obj)
	{
		cout << "in copy \n";
	}
	~A()
	{
		cout << "a= "<

成员函数返回*this

chunli@Linux:~/c++$ cat main.cpp 
#include 
#include 
using namespace std;

class A
{
public:
	void fun()
	{
		cout << "a="<a<<" b="<b<< "  in print"<a = a;
		this->b = b;
		cout << "a="<a<<" b="<b<<"  in init  \n";
	}
	//返回一个引用,相当于返回自身
	A& add(A &a)
	{
		this->a +=  a.a,
		this->b +=  a.b;
		return *this;
	}
	A (const  A &obj)
	{
		cout << "in copy \n";
	}
	~A()
	{
		cout << "a="<

自定义数组类封装 具有以下函数

void arr_set(int n,int value);

int  arr_get(int n);

int  arr_len();

文件1:

chunli@Linux:~/c++$ cat my_arr.h 
#pragma once
class Arr
{
public:
	void arr_set(int n,int value);
	int  arr_get(int n);
	int  arr_len();
	Arr(int n);
	Arr(const Arr &boj);
	~Arr();
private:	
	int len;
	int *arr;
};
chunli@Linux:~/c++$

文件2:

chunli@Linux:~/c++$ cat my_arr.cpp 
#include "my_arr.h"
#include 
using namespace std;
void Arr::arr_set(int n,int value)
{
	this->arr[n] = value;
}
int  Arr::arr_get(int n)
{
	return this->arr[n];
}
int  Arr::arr_len()
{
	return this->len;
}
Arr::Arr(int n)
{
	if(n<1)
	{
		len = 0;
		arr = NULL;
	}
	else
	{
		this->len = n;
		arr = new int [n];
		cout << n <<" init ...\n";
	}
}
Arr::Arr(const Arr &obj)
{
	this->len = obj.len;
	arr = new int [this->len];
	for(int i = 0;ilen;i++)
	{
		this->arr[i] = obj.arr[i] + 1;
	}
	cout << this->len<<" copy ...\n";
}
Arr::~Arr()
{
	if(arr != NULL)
	{
		cout << this->len<<" free ...\n";
		delete [] arr;
		len = 0;
	}
}



chunli@Linux:~/c++$

文件3:

chunli@Linux:~/c++$ cat main.cpp 
#include 
#include "my_arr.h"
#include 
using namespace std;

int main()
{
	
	Arr a1(20);
	for(int i = 0;i

编译运行:

chunli@Linux:~/c++$ g++ -g main.cpp  my_arr.cpp && ./a.out 
20 init ...
0    1    2    3    4    5    6    7    8    9    10    11    12    13    14    15    16    17    18    19    
20 copy ...
1    2    3    4    5    6    7    8    9    10    11    12    13    14    15    16    17    18    19    20    
20 free ...
20 free ...
chunli@Linux:~/c++$

为什么会有友元函数?

在实现类之间数据共享时,减少系统开销,提高效率。

如果类A中的函数要访问类B中的成员(例如:智能指针类的实现),那么类A中该函数要是类B的友元函数。

具体来说:为了使其他类的成员函数直接访问该类的私有变量。

即:允许外面的类或函数去访问类的私有变量和保护变量,从而使两个类共享同一函数。

实际上具体大概有下面两种情况需要使用友元函数:

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

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

chunli@Linux:~/c++$ cat main.cpp 
#include 
#include 
using namespace std;
class A
{
public:
	A(int a,int b)
	{
		this->a = a;
		this->b = b;
	}	
private:
	int a;
	int b;
};
void fun(A *p)
{
	//不能在类的外部访问私有属性
	int n =p->a;
}

int main()
{
	A a1(1,2);
	fun(&a1);
	return 0;
}
编译就报错:
chunli@Linux:~/c++$ g++ -g main.cpp && ./a.out 
main.cpp: In function ‘void fun(A*)’:
main.cpp:13:6: error: ‘int A::a’ is private
  int a;
      ^

把这个函数添加为友元函数就OK了

友元函数 与 位置没有关系

chunli@Linux:~/c++$ cat main.cpp 
#include 
#include 
using namespace std;
class A
{
	friend void fun(A *p);
public:
	A(int a,int b)
	{
		this->a = a;
		this->b = b;
	}	
	int get_a()
	{
		return this->a;
	}
private:
	int a;
	int b;
};
void fun(A *p)
{
	//不能在类的外部访问私有属性
	p->a  = 10;
	int n =p->a;
	cout << n << endl;
}

int main()
{
	A a1(1,2);
	fun(&a1);
	cout << a1.get_a() << endl;
	return 0;
}
chunli@Linux:~/c++$ g++ -g main.cpp && ./a.out 
10
10

友元类:

chunli@Linux:~/c++$ cat main.cpp 
#include 
#include 
using namespace std;
class A
{
	friend class B;
private:
	int a;
};

class B
{
	friend void fun(A *p);
public:
	B(int a)
	{
		a1.a  = a;	//可以直接修改友元类的属性	
	}	
	int get_a()
	{
		return this->a1.a;////可以直接修改友元类的属性
	}
private:
	int a;
	A a1;
};


int main()
{
	B b1(11);
	cout << b1.get_a() << "\n";
	
	return 0;
}
chunli@Linux:~/c++$ g++ -g main.cpp && ./a.out 
11
chunli@Linux:~/c++$

运算符重载,初步

让两个类直接相加减

运算符重载本质是一个函数

约定operator关键字

C++编译器会自动去找运算符

chunli@Linux:~/c++$ cat main.cpp 
#include 
#include 
using namespace std;
class A
{
public:
	A(int a,int b)
	{
		this->a  = a;	
		this->b  = b;	
	}	
	int printf()
	{
		cout <

可以进行运算符重载的符合

不可以进行运算符重载的符合

C++基础4 类 const函数 转全局函数 返回*this 数组类。友元 函数 类 操作符重载

C++基础4 类 const函数 转全局函数 返回*this 数组类。友元 函数 类 操作符重载

【二元操作符】成员函数的运算符重载

此时的成员变量还都是public的

chunli@Linux:~/c++$ cat main.cpp 
#include 
using namespace std;
class A
{
public:
	A operator+(A obj)
	{
		cout << "成员函数的 运算符重载 \n";
		A t(this->a + obj.a +1,this->b + obj.b +1 );
		return t;
	}
	A(int a,int b)
	{
		this->a  = a;	
		this->b  = b;	
	}	
	int printf()
	{
		cout <

【二元操作符】全局函数的运算符重载

此时的成员变量都是private的

chunli@Linux:~/c++$ cat main.cpp 
#include 
using namespace std;
class A
{
	friend A operator+(A &a,A &b);
public:
	A(int a,int b)
	{
		this->a  = a;	
		this->b  = b;	
	}	
	int printf()
	{
		cout <

【二元操作符】成员函数的运算符重载

此时的成员变量都是private的

chunli@Linux:~/c++$ cat main.cpp 
#include 
using namespace std;
class A
{
public:
	A operator+(A obj)
	{
		cout << "成员函数的 运算符重载 \n";
		A t(this->a + obj.a +1,this->b + obj.b +1 );
		return t;
	}
	A(int a,int b)
	{
		this->a  = a;	
		this->b  = b;	
	}	
	int printf()
	{
		cout <

【一元运算符】前置++ 

全局函数  运算符重载

chunli@Linux:~/c++$ cat main.cpp 
#include 
using namespace std;
class A
{
	friend A& operator++(A &a);
public:
	A(int a,int b)
	{
		this->a  = a;	
		this->b  = b;	
	}	
	int printf()
	{
		cout <

【一元运算符】前置++ 

成员函数  运算符重载

chunli@Linux:~/c++$ cat main.cpp 
#include 
using namespace std;
class A
{
public:
	A& operator++()
	{
		cout << "成员函数的 运算符重载 \n";
		this->a++;
		this->b++;
		return *this;	//A& 需要返回一个实体,而不是指针
	}
	A(int a,int b)
	{
		this->a  = a;	
		this->b  = b;	
	}	
	int printf()
	{
		cout <

全局函数  成员函数

前置++  后置++

前置--  后置--

【注意】全局函数的声明 要与友元函数的声明一致

chunli@Linux:~/c++$ cat main.cpp 
#include 
using namespace std;
class A
{
	friend A& operator--(A &a);
	friend A operator--(A &a,int);
public:
	A& operator++()
	{
		cout << "前置++ 一元运算符重载 ";
		this->a++;
		this->b++;
		return *this;	//A& 需要返回一个实体,而不是指针
	}
	A operator++(int)
	{
		cout << "后置++ 一元 运算符重载 ";
		A t = *this;
		this->a++;
		this->b++;
		return t;
	}
	A(int a,int b)
	{
		this->a  = a;	
		this->b  = b;	
	}	
	void printf()
	{
		cout <

有元函数的正真使用场景:

使用cout输出一个自定义类的成员变量,必须修改ostream类源码

在拿不到iostream的源代码的情景下,只能使用友元函数

chunli@Linux:~/c++$ cat main.cpp 
#include 
using namespace std;
class A
{
	friend void operator<<(ostream &friend_ship,A &from);
public:
	A(int a,int b)
	{
		this->a  = a;	
		this->b  = b;	
	}	
	void printf()
	{
		cout <

链式输出对象的信息  cout << a << a;

chunli@Linux:~/c++$ cat main.cpp 
#include 
using namespace std;
class A
{
	friend ostream & operator<<(ostream &friend_ship,A &from);
public:
	A(int a,int b)
	{
		this->a  = a;	
		this->b  = b;	
	}	
	void printf()
	{
		cout <

运算符重载提高:1

等号 = 运算符重载:  支持链式操作

【难点】 释放之前的指针,返回一个引用

chunli@Linux:~/c++$ cat main.cpp 
#include 
#include 
#include 
using namespace std;

class Str
{
public:
	Str(const char *p)
	{
		this->len = strlen(p);
		this->p = (char*)malloc(this->len + 1);
		strcpy(this->p,p);
		this->p[len] = '\0';
		cout << this->p << " init\n";
	}	
	Str(const Str &from)
	{
		this->len = strlen(from.p);
		this->p =(char*)malloc(this->len + 1);
		strcpy(this->p,from.p);
		this->p[this->len] = '\0';
		cout << "in copy \n";
	}
	~Str()
	{
		if(this->p != NULL)
		{
			cout << this->p << " free\n";
			free(this->p);
			this->p = NULL;
			this->len = 0;
		}
	}
	Str& operator=(Str &from)
	{
		if(this->p != NULL)
		{
			free(this->p);	//先把自己之前的指针释放掉
		}
		cout < in = operator\n";
		this->len = strlen(from.p);
		this->p = (char*)malloc(this->len + 1);
		strcpy(this->p,from.p);
		this->p[len] = '\0';
		return *this;
	}
private:
	char *p;
	int  len;
};


int main()
{
	Str s1("Hello");
	Str s2("Linux");
	Str s3("Google");
	s1 = s2 = s3;	//对象的赋值操作s1 = s2 ,不会调用赋值构造函数
	return 0;
}
chunli@Linux:~/c++$ g++ -Wall -g main.cpp && ./a.out 
Hello init
Linux init
Google init
Google -> in = operator
Google -> in = operator
Google free
Google free
Google free

中括号[]运算符重载,数组类的

【难点】:函数当右值,函数当左值

chunli@Linux:~/c++$ cat main.cpp 
#include 
using namespace std;

class Arr
{
public:
	Arr(int n)
	{
		this->len = n;
		p = new int[n];	
	}	
	~Arr()
	{
		delete [] p;
	}
	int & operator[](int i)
	{
		return p[i];
	}
	int  len;
	int  *p;
};

int main()
{
	Arr a1(16);
	for(int i = 0;i

【强化数组类练习!】等号=运算符重载,中括号[]运算符重载

chunli@Linux:~/c++$ cat main.cpp 
#include 
using namespace std;
class Arr
{
public:
	Arr(int n)
	{
		this->len = n;
		p = new int[n];	
	}	
	~Arr()
	{
		if(p != NULL)
		{
			delete [] p;
			p = NULL;
		}
	}
	int & operator[](int i)
	{
		return p[i];
	}
	Arr & operator=(Arr &from)
	{
		if(this->p != NULL)
		{
			delete [] p;
		}
		this->len = from.len;
		this->p = new int[this->len];
		for(int i=0;ip[i] = from.p[i];
		}
		return *this;	
	}
	void out()
	{
		for(int i = 0;ilen;i++)
		{
			cout << this->p[i] << "\t";
		}
		cout << "\n";
	}
	void init(int num)
	{
		for(int i = 0;ilen;i++)
		{
			this->p[i]  = i + num;
		}
	}
	int  len;
	int  *p;
};



int main()
{
	Arr a1(16);	a1.init(1);	a1.out();
	Arr a2(10);	a2.init(2);	a2.out();
	a1 = a2;	a1.out();
	return 0;
}
chunli@Linux:~/c++$ g++ -Wall -g main.cpp && ./a.out 
1	2	3	4	5	6	7	8	9	10	11	12	13	14	15	16	
2	3	4	5	6	7	8	9	10	11	
2	3	4	5	6	7	8	9	10	11	

数组的 相等== 运算操作符重载,不等于!= 操作符重载

chunli@Linux:~/c++$ cat main.cpp 
#include 
using namespace std;
class Arr
{
public:
	Arr(int n)
	{
		this->len = n;
		p = new int[n];	
	}	
	~Arr()
	{
		if(p != NULL)
		{
			delete [] p;
			p = NULL;
		}
	}
	int & operator[](int i)
	{
		return p[i];
	}
	Arr & operator=(Arr &from)
	{
		if(this->p != NULL)
		{
			delete [] p;
		}
		this->len = from.len;
		this->p = new int[this->len];
		for(int i=0;ip[i] = from.p[i];
		}
		return *this;	
	}
	bool operator!=(Arr &from)
	{
		if(this->len != from.len)
		{
			return true;
		}
		for(int i = 0;ip[i] != from.p[i])
			{
				return true;
			}
		}
		return false;
	}
	bool operator==(Arr &from)
	{
		if(this->len != from.len)
		{
			return false;
		}
		for(int i = 0;ip[i] != from.p[i])
			{
				return false;
			}
		}
		return true;
	}
	void out()
	{
		for(int i = 0;ilen;i++)
		{
			cout << this->p[i] << "\t";
		}
		cout << "\n";
	}
	void init(int num)
	{
		for(int i = 0;ilen;i++)
		{
			this->p[i]  = i + num;
		}
	}
	int  len;
	int  *p;
};



int main()
{
	Arr a1(16);	a1.init(1);	a1.out();
	Arr a2(10);	a2.init(2);	a2.out();
	a1 = a2;	a1.out();

	Arr a3(10);	a3.init(1);
	Arr a4(10);	a4.init(1);
	if(a3 == a4)
	{
		cout << "a3 == a4 \n";
	} 
	else
	{
		cout << "a3 != a4 \n";
	}

	a4.init(2);	//修改a4数组的值
	if(a3 != a4)
	{
		cout << "a3 != a4 \n";
	} 
	else
	{
		cout << "a3 == a4 \n";
	}




	return 0;
}
chunli@Linux:~/c++$ g++ -Wall -g main.cpp && ./a.out 
1	2	3	4	5	6	7	8	9	10	11	12	13	14	15	16	
2	3	4	5	6	7	8	9	10	11	
2	3	4	5	6	7	8	9	10	11	
a3 == a4 
a3 != a4

运算符结合方向:

C++基础4 类 const函数 转全局函数 返回*this 数组类。友元 函数 类 操作符重载

C++基础4 类 const函数 转全局函数 返回*this 数组类。友元 函数 类 操作符重载






当前名称:C++基础4类const函数转全局函数返回*this数组类。友元函数类操作符重载
网址分享:http://cdweb.net/article/jpheip.html