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

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

[email protected]:~/c++$ cat main.cpp 
#include <iostream>
#include <stdlib.h>
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指针本身的值,编译也不通过

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

[email protected]:~/c++$ cat main.cpp 
#include <iostream>
#include <stdlib.h>
using namespace std;

class A
{
public:
	void fun()
	{
		cout << "a="<<this->a<<" b="<<this->b<< "  in fun"<<endl;
	}
	A(int a=0,int b=0)
	{
		this->a = a;
		this->b = b;
		cout << "a="<<this->a<<" b="<<this->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= "<<a << " b="<<b <<" free\n"; 
	}
	 

public:
	int  a;
	int  b;
};

//把成员函数转成全局函数
A fun(A &a1,A &a2)
{
	A a3;
	return a3;
}

void fun1()
{
	cout << "--------  in fun1 ------------------- \n";
	A a1(1,2);
	A a2(3,4);
	A a3 = a1.add(a2);	a3.fun();
}
void fun2()
{
	cout << "--------  in fun2 ------------------- \n";
	A a1(1,2);
	A a2(3,4);
	A a3(5,5);	 a3 = a1.add(a2);        a3.fun();
}
int main()
{
	fun1();
	fun2();
	return 0;
}

[email protected]:~/c++$ g++ -g main.cpp  && ./a.out 
--------  in fun1 ------------------- 
a=1 b=2  in init  
a=3 b=4  in init  
a=4 b=6  in init  
a=4 b=6  in fun
a= 4 b=6 free
a= 3 b=4 free
a= 1 b=2 free
--------  in fun2 ------------------- 
a=1 b=2  in init  
a=3 b=4  in init  
a=5 b=5  in init  
a=4 b=6  in init  
a= 4 b=6 free
a=4 b=6  in fun
a= 4 b=6 free
a= 3 b=4 free
a= 1 b=2 free

成员函数返回*this

[email protected]:~/c++$ cat main.cpp 
#include <iostream>
#include <stdlib.h>
using namespace std;

class A
{
public:
	void fun()
	{
		cout << "a="<<this->a<<" b="<<this->b<< "  in print"<<endl;
	}
	A(int a=0,int b=0)
	{
		this->a = a;
		this->b = b;
		cout << "a="<<this->a<<" b="<<this->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="<<a << " b="<<b <<"  free\n"; 
	}
	 

public:
	int  a;
	int  b;
};

int main()
{
	A a1(1,2);
	A a2(3,4);
	a1.add(a2);	a1.fun();
	return 0;
}

[email protected]:~/c++$ g++ -g main.cpp  && ./a.out 
a=1 b=2  in init  
a=3 b=4  in init  
a=4 b=6  in print
a=3 b=4  free
a=4 b=6  free
[email protected]:~/c++$

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

void arr_set(int n,int value);

int  arr_get(int n);

int  arr_len();

文件1:

[email protected]:~/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;
};
[email protected]:~/c++$

文件2:

[email protected]:~/c++$ cat my_arr.cpp 
#include "my_arr.h"
#include <iostream>
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;i<this->len;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;
	}
}

[email protected]:~/c++$

文件3:

[email protected]:~/c++$ cat main.cpp 
#include <iostream>
#include "my_arr.h"
#include <stdlib.h>
using namespace std;

int main()
{

	Arr a1(20);
	for(int i = 0;i<a1.arr_len();i++)
	{
		a1.arr_set(i,i);
	}
	for(int i = 0;i<a1.arr_len();i++)
	{
		cout << a1.arr_get(i) << "    ";
	}
	cout << endl;

	Arr a2 = a1;	//等号操作,C++编译器会调用拷贝构造函数
	for(int i = 0;i<a2.arr_len();i++)
	{
		cout << a2.arr_get(i) << "    ";
	}
	cout << endl;
	return 0;
}

编译运行:

[email protected]:~/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 ...
[email protected]:~/c++$

为什么会有友元函数?

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

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

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

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

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

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

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

[email protected]:~/c++$ cat main.cpp 
#include <iostream>
#include <stdlib.h>
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;
}
编译就报错:
[email protected]:~/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了

友元函数 与 位置没有关系

[email protected]:~/c++$ cat main.cpp 
#include <iostream>
#include <stdlib.h>
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;
}
[email protected]:~/c++$ g++ -g main.cpp && ./a.out 
10
10

友元类:

[email protected]:~/c++$ cat main.cpp 
#include <iostream>
#include <stdlib.h>
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;
}
[email protected]:~/c++$ g++ -g main.cpp && ./a.out 
11
[email protected]:~/c++$

运算符重载,初步

让两个类直接相加减

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

约定operator关键字

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

[email protected]:~/c++$ cat main.cpp 
#include <iostream>
#include <stdlib.h>
using namespace std;
class A
{
public:
	A(int a,int b)
	{
		this->a  = a;
		this->b  = b;
	}
	int printf()
	{
		cout <<a<<" "<<b<<endl;
	}
	int a;
	int b;
};

A operator+(A &a,A &b)
{
	cout << "Hello World \n";
	A t(a.a+b.a,a.b+b.b);
	return t;
}
int main()
{
	A a1(1,1);
	A a2(2,2);
	A a3 = a1+a2;
	a3.printf();
	return 0;
}
[email protected]:~/c++$ g++ -g main.cpp && ./a.out 
Hello World 
3 3
[email protected]:~/c++$

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

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

时间: 2024-10-19 05:22:51

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

C++ 模板类友元之输出流操作符重载

几个关键点: 需要前置声明!--奇怪的是别人告诉我也可以不需要,但我这里不行! 友元函数的函数名后面的<>,必须要有. #include <stdio.h> #include <iostream> using namespace std; //前置声明,你妹啊 template<class T> class A; template<class T> ostream &operator<< (ostream &out,

C++--操作符重载 复数类

一.操作符重载 Q:下面的复数解决方案是否可行? class Complex { public: int a; int b; }; int main() { Complex c1={1,2}; Complex c2={3,4}; Complex c3=c1+c2; return 0; } 该段代码想要实现的是将两个复数类进行相加得出第三个类代码实现的运行结果由上面的结果图可以得知,出现的错误是无法匹配+号操作符的操作,同时出现 的潜在问题是a与b是public成员,在实际的操作中应将a与b设置为

C++ Primer 学习笔记33_面向对象编程(4)--虚函数与多态(一):多态、派生类重定义、虚函数的访问、 . 和-&gt;的区别、虚析构函数、object slicing与虚函数

C++ Primer学习笔记33_面向对象编程(4)--虚函数与多态(一):多态.派生类重定义.虚函数的访问. . 和->的区别.虚析构函数.object slicing与虚函数 一.多态 多态可以简单地概括为"一个接口,多种方法",前面讲过的重载就是一种简单的多态,一个函数名(调用接口)对应着几个不同的函数原型(方法). 更通俗的说,多态行是指同一个操作作用于不同的对象就会产生不同的响应.或者说,多态性是指发出同样的消息被不同类型的对象接收时有可能导致完全不同的行为. 多态行分

【C/C++学院】(8)全局函数和类成员函数转化/友元/操作符重载

1.全局函数和类成员函数转化 全局函数和成员函数的相互转化:只需要修改一个指向本类的this指针: #include <iostream> using namespace std; class Test { public: Test(int a, int b) { this->a = a; this->b = b; } //成员函数 Test &Gadd2(Test &t2) { this->a = this->a + t2.a; this->b

重载运算符:类成员函数or友元函数

类成员函数: bool operator ==(const point &a)const { return x==a.x; } 友元函数: friend bool operator ==(const point &a,const point &b) { return a.x==b.x; } 两种重载方式的比较: (1)单目运算符.=.().[].->使用类成员函数,其它双目运算符使用友元函数 (2)类型转换函数只能定义为类成员函数 (3)运算会修改类成员是使用类成员函数 (4

C++之友元机制(友元函数和友元类)

一.为什么引入友元机制? 总的来说就是为了让非成员函数即普通函数或其他类可以访问类的私有成员,这确实破坏了类的封装性和数据的隐蔽性,但为什么要这么做呢? (c++ primer:尽管友元被授予从外部访问类的私有部分的权限,但它并不与面向对象的编程思想相悖,相反,他们提高了公有接口的灵活性).要理解这句话,就必须知道友元形成的过程:(任何函数,或者成员函数或者类想成为某个类的友元,这是由这个类来决定的,而不能从外部强加友情) 我们已知道类具有封装和信息隐藏的特性.只有类的成员函数才能访问类的私有成

友元函数友元类.

友元能够理解为是类的"朋友".它能够訪问类的保护和私有成员.友元的作用在于提高程序的执行效率,可是,它破坏了类的封装性和隐藏性.友元能够是一个函数,该函数被称为友元函数:友元也能够是一个类,该类被称为友元类. 一.友元函数 友元函数是在类外定义的一个函数,不是类的成员函数. 这个函数能够是普通的C++函数,或者是其它类的成员函数.即普通友元函数和友元成员函数.友元函数是定义在类外部.但须要在类体内进行说明,为了与该类的成员函数加以差别.在说明时前面加以keywordfriend.友元函

C++:友元(非成员友元函数、成员友元函数、友元类)

3.8  友元:友元函数和友元类 友元函数 :既可以是不属于任何类的非成员函数,也可以是另一个类的成员函数,统称为友元函数.友元函数不是当前类的成员函数,而是独立于类的外部函数,但它可以访问该类所有的成员,包括私有成员.保护成员和公有成员.在类中声明友元函数时,需在其函数名前加上关键字friend,此声明可以放在公有部分.也可以放在保护和私有部分.友元函数可以定义在类部,也可以定义在类的外部. 3.8.1 将非成员函数声明为友元函数 //1.将非成员函数声明为友元函数 // 例3.33 友元函数

c++友元函数与友元类

1. 友元函数和友元类的需要: 类具有封装和信息隐藏的特性. 只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的. 非成员函数可以访问类中的公有成员,但是如果将数据成员都定义为公有的,这又破坏了隐藏的特性. 另外,应该看到在某些情况下,特别是在对某些成员函数多次调用时,由于参数传递,类型检查和安全性检查等都需要时间开销,而影响程序的运行效率. 2. 为了解决上述问题,提出一种使用友元的方案. 友元是一种定义在类外部的普通函数,但它需要在类体内进行说明,为了与该类的成员函数

模板类的友元函数

非模板友元函数 模板类的非模板友元函数是说该模板类的友元函数只是一个普通函数,并且该函数是非模板函数或该函数不视为模板函数.这里包含了两种情况,下面分别就两个例子进行说明. • 函数是非模板函数 这一类友元函数特点是不带有参数列表,例如:friend void Fn().这类友元函数通常可以用于全局对象的访问. #include <iostream> using namespace std; template <class T> class MyNumber { private: