1. 程式人生 > 其它 >記錄C++的學習2

記錄C++的學習2

技術標籤:C++學習

記錄c++的學習2

(僅供參考,歡迎大家交流學習)
2021.1.10

4、友元:

4.1全域性函式做友元:

1、友元的目的就是讓一個函式或者類訪問另一個類中私有成員
2、友元的關鍵字為friend
3、友元的三種實現
(1)全域性函式做友元
(2)類做友元
(3)成員函式做友元
4、友元是C++提供的一種破壞資料封裝和資料隱藏的機制。
5、若一個類為另一個類的友元,則此類的所有成員函式都能訪問對方類的私有成員。
6、單向性:如果宣告B類是A類的友元, B類的成員函式就可以訪問A類的私有和保護資料,但A類的成員函式卻不能訪問B類的私有、保護資料。不可傳遞性,不可繼承性:。

下面展示一些 程式碼

#include <iostream>
#include <string>
using namespace std;
class Person
{
	//友元函式宣告:
	friend void test01(Person *p);
public:
	Person()
	{
		home="我家";
		phone="我手機";
	}
	string home;
private:
	string phone;
};
//全域性函式:
void test01(Person *p)//用指標或者是用引用都可以
{//不過用指標就必須是p->home,引用是p.home
cout<<"好朋友來"<<p->home<<endl; cout<<"好朋友可以看"<<p->phone<<endl; } void test02() { Person p; test01(&p);//傳入指標,所以用&p } int main() { test02(); system("pause"); return 0; }

在這裡插入圖片描述

4.2 類做友元:

下面展示一些 程式碼

#include <iostream>
#include <string> using namespace std; //類做友元: //若一個類為另一個類的友元,則此類的所有成員函式都能訪問對方類的私有成員。 class A { friend class B;//賦予B類友元的許可權 public: void Display()//設定一個函式輸出x的值 { cout<<x<<endl; } private: int x; }; class B { public: void Set(int i) { a.x=i; /*因為A類賦予了B類友元關係,故在B類中可以直接訪問 A類物件a的私有資料成員*/ } void Display() { a.Display(); } private: A a; }; void test01() { B a; a.Set(3); a.Display(); } int main() { test01(); system("pause"); return 0; }

在這裡插入圖片描述

4.3 成員函式做友元:

5、運算子過載:

5.1 加號運算子過載:

#include <iostream>
using namespace std;
//加號運算子過載
//1、成員函式過載+號
class Person
{
public:
	/*Person operator+(Person &p)
	{
		Person temp;
		temp.a=this->a+p.a;
		temp.b=this->b+p.b;
		return temp;
	}*/
int a;
int b;
};
//void test01()
//{
//	Person p1;
//	p1.a=10;
//	p1.b=10;
//	Person p2;
//	p2.a=10;
//	p2.b=10;
//	Person p3;
//	p3=p1+p2;
//	cout<<"P3.a="<<p3.a<<endl;
//	cout<<"P3.b="<<p3.b<<endl;
//}
//2、全域性函式過載+號
Person operator+(Person &p3,Person &p4)
{
	Person temp1;
	temp1.a=p3.a+p4.a;
	temp1.b=p3.b+p4.b;
	return temp1;
}
Person operator+(Person &p3,int num)
{
	Person temp1;
	temp1.a=p3.a+num;
	temp1.b=p3.b+num;
	return temp1;
}
void test02()
{
	Person p3;
	p3.a=15;
	p3.b=15;
	Person p4;
	p4.a=15;
	p4.b=15;
	Person p5;
	p5=p3+p4;
	cout<<"P5.a="<<p5.a<<endl;
	cout<<"P5.b="<<p5.b<<endl;
    Person  p6;
	p6=p3+100;
	cout<<"P6.a="<<p6.a<<endl;
	cout<<"P6.b="<<p6.b<<endl;
}
//成員函式過載本質呼叫:
//Person p3=p1.operator+(p2);

//全域性函式過載本質呼叫
//Person p3=operator+(p1,p2);

//運算子過載,也可以發生函式過載

int main()
{
	
	test02();
	system("pause");
	return 0;
}

在這裡插入圖片描述

5.2 左移運算子過載:

#include <iostream>
using namespace std;
class Person
{
	friend ostream & operator<<(ostream &cout,Person &p);//運用友元函式訪問private
public:
	Person (int a,int b)
	{
		this->a=a;
		this->b=b;
	}
private:
	int a;
	int b;

};
/*利用成員函式過載 左移運算子 p.operator<<(cout) 簡化為p<<cout。
不會利用成員函式過載<<運算子,因為無法實現cout在左側*/
//只能利用全域性函式過載左移運算子:
ostream & operator<<(ostream &cout,Person &p)//本質 operator<<(cout,p),簡化為cout<<p
//輸出流物件,全域性只能有一個,用引用的方式傳遞。
{
	cout <<"a="<<p.a<<endl;
	cout <<"b="<<p.b<<endl;
	return cout;
}
void test01()
{
	Person p(1024,1024);
	cout<<p;
}
int main()
{
	test01();
	system("pause");
	return 0;
}

在這裡插入圖片描述

5.3 遞增運算子過載:

#include <iostream>
using namespace std;
//過載遞增運算子

//自定義整型
class MyInteger
{
	friend ostream & operator<<(ostream& cout,MyInteger &myint);
public:
	MyInteger()
	{
		num=0;
		  
	}
	//過載前置++運算子
	MyInteger& operator++()
	//必須用引用&,目的是一直對一個數據進行操作
	{
	//先進行++運算
	num++;
	//再將自身做一個返回
	return *this;//*this,將自身作為返回
	}
	//過載後置++運算子
	//int代表佔位引數,可以用於區分前置和後置遞增
	MyInteger operator++(int)//後置返回值,前置返回引用
	{
	//先記錄當時結果
	MyInteger temp=*this;
	//後遞增
	num++;
	//最後將記錄結果做一個返回操作
	return temp;
	}
private:
	int num;

};
void test01()
{
	MyInteger myint;
	cout<<++myint<<endl;
	cout<<myint<<endl;
}
void test02()
{
	MyInteger myint;
	cout<<myint++<<endl;
	cout<<myint<<endl;
}
ostream & operator<<(ostream& cout,MyInteger &myint)
{
	cout<<myint.num;
	return cout;
}
int main()
{
	cout<<"前置++運算子:"<<endl;
	test01();
	cout<<"後置++運算子:"<<endl;
	test02();
	system("pause");
	return 0;
}

在這裡插入圖片描述

5.4 賦值運算子過載:

1、賦值運算子operator=,對屬性進行拷貝,如果有屬性指向堆區,做賦值操作時,也會出現深淺拷貝的問題。

#include <iostream>
using namespace std;
//賦值運算子過載
class Person
{
public:
	Person(int age1)
	{
	age=new int(age1);
	}
	~Person()
	{
		//堆區記憶體重複釋放,會導致程式崩潰。
		if(age!=NULL)
		{
			delete age;
			age=NULL;
		}
	}
	//過載 賦值運算子
	Person& operator=(Person &p)
	{
		//編譯器提供淺拷貝age=p.age;

		//應該先判斷是否有屬性在堆區,如果有,先釋放乾淨,然後再深拷貝。
		if(age!=NULL)
		{
			delete age;
			age=NULL;
		}
		age=new int (*p.age);//深拷貝
		//返回物件本身
		return *this;
	}
  int *age;
};
void test01()
{
	Person p1(18);
	Person p2(20);
	Person p3(25);
	p3=p2=p1;
	p2=p1;//賦值操作
	cout<<"p1的年齡為:"<<*p1.age<<endl;
	cout<<"p2的年齡為:"<<*p2.age<<endl;
	cout<<"p3的年齡為:"<<*p3.age<<endl;
}
int main()
{
	test01();
	system("pause");
	return 0;
}

在這裡插入圖片描述