大话C++类与对象(三)

友元函数

友元函数是一种定义在类外部的普通函数,其特点是能够访问类中私有成员和保护成员,即类的访问权限的限制对其不起作用。

友元函数需要在类体内进行说明,在前面加上关键字friend

例:
在这里插入图片描述

友元函数特点:

  • 1.友元函数不是成员函数,用法也与普通的函数完全一致,只不过它能访问类中所有的数据。
  • 2.友元函数破坏了类的封装性和隐蔽性,使得非成员函数可以访问类的私有成员。
  • 3.一个类的友元可以自由地用该类中的所有成员。

示例C++代码如下:

#include<iostream>
using namespace std;

class A{
		float x, y;
	public:
		A(float a, float b)
		{
			x = a;
			y = b;
		}
		float Sum()
		{
			return x + y;
		}
		friend float Sum(A &a)
		{
			return a.x + a.y;
		}
}; 

int main()
{
	A t1(4, 5), t2(10, 20);
	cout << t1.Sum() << endl;
	cout << Sum(t2) << endl;
	return 0;
}

运行结果如下:
在这里插入图片描述
代码分析:
在这里插入图片描述
有关友元函数的使用,说明如下:

  • 1.友元函数不是类的成员函数
  • 2.友元函数近似于普通的函数,它不带有this指针,因此必须将对象名或对象的引用作为友元函数的参数,这样才能访问到对象的成员。

友元函数与一般函数的不同点在于:

1、友元函数必须在类的定义中声明,其函数体可在类内定义,也可在类外定义;
2、它可以访问该类中的所有成员(公有的、私有的和保护的),而一般函数只能访问类中的公有成员。

示例C++代码如下:

#include<iostream>
using namespace std;

class A{
	float x, y;
	public:
		A(float a, float b)
		{
			x = a;
			y = b;
		}
		float Getx()
		{
			return x;
		}
		float Gety()
		{
			return y;
		}
		float Sum()
		{
			return x + y;
		}
		friend float Sum(A &);
};

float Sumxy(A &a)
{
	return a.Getx() + a.Gety();
}

float Sum(A &a)
{
	return a.x + a.y;
}

int main()
{
	A t1(1, 2), t2(10, 20), t3(100, 200);
	cout << t1.Sum() << endl;
	cout << Sum(t2) << endl;
	cout << Sumxy(t3) << endl;
	return 0;
}

运行结果如下:
在这里插入图片描述
代码分析如下:
在这里插入图片描述
Attention!!!
1、友元函数不受类中访问权限关键字的限制,可以把它放在类的私有部分,放在类的公有部分或放在类的保护部分,其作用都是一样的。换言之,在类中对友元函数指定访问权限是不起作用的。
2、友元函数的作用域与一般函数的作用域相同。
3、谨慎使用友元函数。通常使用友元函数来取对象中的数据成员值,而不修改对象中的成员值,则肯定是安全的。

大多数情况是友元函数是某个类的成员函数,即A类中的某个成员函数是B类中的友元函数,这个成员函数可以直接访问B类中的私有数据。这就实现了类与类之间的沟通。
在这里插入图片描述
注意:一个类的成员函数作为另一个类的友元函数时,应先定义友元函数所在的类。
在这里插入图片描述
示例C++代码如下:

#include<iostream>
using namespace std;

class B;

class A{
	float x, y;
	public:
		A(float a, float b)
		{
			x = a;
			y = b;
		}
		float Sum(B &);
		void Show()
		{
			cout << "x = " << x << '\t' << "y = " << y << endl;
		}
};

class B{
	float m, n;
	public:
		B(float a, float b)
		{
			m = a;
			n = b;
		}
		friend float A::Sum(B &);
};

float A::Sum(B &b)
{
	x = b.m + b.n;
	y = b.m - b.n;
}

int main()
{
	A a1(3, 5);
	B b1(10, 20);
	a1.Sum(b1);
	a1.Show();
	return 0;
}

运行结果如下:
在这里插入图片描述

友元类

在这里插入图片描述
示例C++代码如下:

#include<iostream>
using namespace std;
//class B;
const float PI = 3.1415926;

class A{
	float r;
	float h;
	public:
		A(float a, float b)
		{
			r = a;
			h = b;
		}
		float Getr()
		{
			return r;
		}
		float Geth()
		{
			return h;
		}
		friend class B;
};

class B
{
	int number;
	public:
		B(int n = 1)
		{
			number = n;
		}
		void Show(A &a)
		{
			cout << PI * a.r * a.h * number << endl;
		}
};

int main()
{
	A a1(25, 40), a2(10, 40);
	B b1(2);
	b1.Show(a1);
	b1.Show(a2);
	return 0;
}

运行结果如下:
在这里插入图片描述
对比上面两个代码我们会发现,前者先声明了一个class B,而后者却不需要。这是因为如果为声明类B,则在前一个代码中,class A中成员函数Sum的参数类型是B,而编译器从上往下运行到成员函数Sum这里一直没找到关于类B的声明,所以要提前声明类B,而上面这个代码为何不需要呢?因为friend class B;编译器会接着往下找关于B类的声明定义,所以不需要提前声明B

不管是按哪一种方式派生,基类的私有成员在派生类中都是不可见的。
如果在一个派生类中要访问基类中的私有成员,可以将这个派生类声明为基类的友元。

示例C++代码如下:

#include<iostream>
using namespace std;

class M{
		friend class N;		//N为M的友元,可直接使用M中的私有成员 

		int i, j;
		void show()
		{
			cout << "i = " << i << '\t' << "j = " << j << endl;
		}
	public:
		M(int a = 0, int b = 0)
		{
			i = a;
			j = b;
		} 
};

class N:public M{
	public:
		N(int a = 0, int b = 0):M(a, b)
		{
		}
		void Print()
		{
			show();
			cout << "i + j = " << i + j<< endl;
		}
};

int main()
{
	N n1(10, 20);
	M m1(100, 200);
	n1.Print();
	return 0;
}

运行结果如下:
在这里插入图片描述

综合题

(1)

定义描述职工档案的类Archives,私有数据成员为职工号(No)、姓名(Name[8])、性别(Sex)、年龄(Age)。成员函数有:构造函数、显示职工信息的函数Show()。再由职工档案类派生出职工工资类Laborage,在职工工资类Laborage中新增数据成员:应发工资(SSalary)、社保金(Security)、实发工资(Fsalary),其成员函数有:构造函数,计算实发工资的函数Count(),计算公式为:实发工资=应发工资-社保金。显示职工档案及工资的函数Display()。在主函数中用Laborage类定义职工对象lab,并赋初始值(1001,”Cheng”,’M’,21,2000,100),然后显示职工档案与工资

详细C++代码如下:

#include<bits/stdc++.h>
using namespace std;

class Archives{
	private:
		int No;
		char Name[8];
		char Sex;
		int Age;
	public:
		void Show();
		Archives(int no, char *p, char s, int age)
		{
			No = no;
			strcpy(Name, p);
			Sex = s;
			Age = age;
		}
};

void Archives::Show()
{
	cout << "No." << No << endl;
	cout << "Name:" << Name << endl;
	cout << "Sex:" << Sex << endl;
	cout << "Age:" << Age << endl;
}	

class Laborage:public Archives{
	float SSalary;
	float Security;
	float Fsalary;
	public:
		Laborage(int no, char *p, char s, int age, float salary, float security):Archives(no, p, s, age)
		{
			SSalary = salary;
			Security = security;
			Count();
		}
		void Count()
		{
			Fsalary = SSalary - Security;
		}
		void Display()
		{
			Show();
			cout << "SSalary:" << SSalary << endl;
			cout << "Security:" << Security << endl;
			cout << "Fsalary:" << Fsalary << endl;
		}
};

int main()
{
	Laborage lab(1001, "Cheng", 'M', 21, 2000, 100);
	lab.Display();
	return 0;
}

运行结果如下:
在这里插入图片描述

(2)

定义描述矩形的类Rectangle,其数据成员为矩形的中心坐标(X,Y)、长(Length)与宽(Width)。成员函数为计算矩形面积的函数Area()与构造函数。再定义描述圆的类Circle,其数据成员为圆的中心坐标(X,Y)与半径R,其成员函数为构造函数。再由矩形类与圆类多重派生出长方体类Cuboid,其数据成员为长方体的高(High)与体积(Volume)。成员函数为:构造函数,计算体积的函数Vol(),显示矩形坐标(X,Y)、长方体的长、宽、高与体积的函数Show()。主函数中用长方体类定义长方体对象cub,并赋初始值(10,10,10,20,30,30,10,10),最后显示长方体的矩形坐标(X,Y)与长方体的长、宽、高与体积。

详细C++代码如下:

#include<bits/stdc++.h>
using namespace std;
#define PI 3.1415926

class Rectangle{
	private:
		float X, Y;
		float Length, Width;
	public:
		Rectangle(float x, float y, float length, float width)
		{
			X = x;
			Y = y;
			Length = length;
			Width = width;
		}
		float Area()
		{
			return Length * Width;
		}
		float Getx()
		{
			return X;
		}
		float Gety()
		{
			return Y;
		}
		float GetLen()
		{
			return Length;
		}
		float GetWidth()
		{
			return Width;
		}
		
};

class Circle{
	private:
		float X, Y;
		float R;
	public:
		Circle(int x, int y, int r)
		{
			X = x;
			Y = y;
			R = r;
		}
		double Area()
		{
			return R * R * PI;
		}
};

class Cuboid:public Rectangle, public Circle{
	private:
		float High, Volume;
	public:
		Cuboid(float x, float y, float length, float width, int xx, int yy, int r, float high):Rectangle(x, y, length, width), Circle(xx, yy, r){
		High = high;
		Vol();
		}
		void Vol()
		{
			Volume = High * Rectangle::Area();
		} 
		void Show()
		{
			cout << "(X, Y) = " << Getx() << ", " << Gety() << endl;
			cout << "Length:" << GetLen() << "   Width:" << GetWidth() << "   High:" << High << endl;
			cout << "Volume:" << Volume << endl;
		}
};

int main()
{
	Cuboid cub(10, 10, 10, 20, 30, 30, 10, 10);
	cub.Show();
	return 0;
}

运行结果如下:
在这里插入图片描述

(3)

定义个人信息类Person,其数据成员有姓名、性别、出生年月。并以Person为基类定义一个学生的派生类Student,增加描述学生的信息:班级、学号、专业、英语成绩和数学成绩。再由基类Person定义一个职工的派生类Employee,增加描述职工的信息:部门、职务、工资。编写程序实现学生与职工信息的输入与输出。

详细C++代码如下:

#include<bits/stdc++.h>
using namespace std;

class Person{
	private:
		char Name[20];
		char sex;
		char BirthDate[20];
	public:
		Person(char *p, char s, char *b)
		{
			strcpy(Name, p);
			sex = s;
			strcpy(BirthDate, b);
		}
		char *GetName()
		{
			return Name;
		}
		char Getsex()
		{
			return sex;
		}
		char * GetBirthDate()
		{
			return BirthDate;
		}
};

class Student:public Person{
	int Classn;
	int Snum;
	char Major[20];
	float English;
	float Math; 
	public:
		Student(char *p, char s, char *b, int classn, int snum, char *m, float english, float math):Person(p, s, b)
		{
			Classn = classn;
			Snum = snum;
			strcpy(Major, m);
			English = english;
			Math = math;
		}
		void ShowS()
		{
			cout << "Name:" << GetName() <<endl;
			cout << "sex:" << Getsex() << endl;
			cout << "BirthDate:" << GetBirthDate() << endl;
			cout << "Classn:" << Classn << endl;
			cout << "Snum:" << Snum << endl;
			cout << "Major:" << Major << endl;
			cout << "English:" << English << endl;
			cout << "Math:" << Math << endl;
		}
};

class Employee:public Person{
	char Deployment[20];
	char Task[20];
	float Salary;
	public:
		Employee(char *p, char s, char *b, char *deploy, char *task, float salary):Person(p, s, b)
		{
			strcpy(Deployment, deploy);
			strcpy(Task, task);
			Salary = salary;
		}
		void ShowE()
		{
			cout << "Name:" << GetName() <<endl;
			cout << "sex:" << Getsex() << endl;
			cout << "BirthDate:" << GetBirthDate() << endl;
			cout << "Deployment:" << Deployment << endl;
			cout << "Task:" << Task << endl;
			cout << "Salary:" << Salary << endl; 
		}
};

int main()
{
	char name[20], sex, birthdate[20];
	int classn, snum;
	char major[20];
	float English, Math;
	cout << "please input student's name(char *), sex(char), birthdate(char), class(int), studentnumber(int), major(char *), English(float) and Math(float):" << endl;
	cin >> name >> sex >> birthdate >> classn >> snum >> major >> English >> Math;
	
	Student stud(name, sex, birthdate, classn, snum, major, English, Math);
	char deployment[20], task[20];
	float salary;
	cout << "please input Employee's name(char *), sex(char), birthdate(char), deployment(char *), task(char *) and salary(float):" << endl;
	cin >> name >> sex >> birthdate >> deployment >> task >> salary;
	
	Employee employee(name, sex, birthdate, deployment, task, salary);
	stud.ShowS();
	employee.ShowE();
	return 0;
}

运行结果如下:
在这里插入图片描述

(4)

定义一个复数类Complex,复数的实部Real与虚部Image定义为私有数据成员。用复数类定义复数对象c1、c2、c3,用默认构造函数将c1初始化为c1=20+40i ,将c2初始化为c2=0+0i,用拷贝构造函数将c3初始化为c3=20+40i。用公有成员函数Dispaly()显示复数c1、c2与c3 的内容。

#include<iostream>
using namespace std;

class Complex{
	private:
		int Real;
		int Image;
	public:
		Complex()
		{
			Real = 0;
			Image = 0;
		}
		Complex(int real, int image)
		{
			Real = real;
			Image = image;
		}
		void Display()
		{
			cout << Real << "+" << Image << "i" << endl;
		}
		Complex(Complex &a)
		{
			Real = a.Real;
			Image = a.Image;
		}
};

int main()
{
	Complex c1(20, 40), c2, c3;

	c3 = Complex(c1);
	c1.Display();
	c2.Display();
	c3.Display();
	
	return 0;
}

运行结果如下:
在这里插入图片描述

(5)

定义一个学生成绩类Score,描述学生成绩的私有数据成员为学号(No)、姓名(Name[8])、数学(Math)、物理(Phi)、数据结构(Data)、平均分(ave)。定义能输入学生成绩的公有成员函数Write(),能计算学生平均分的公有成员函数Average(),能显示学生成绩的公有成员函数Display()。在主函数中用Score类定义学生成绩对象数组s[3]。用Write()输入学生成绩,用Average()计算每个学生的平均分,最后用Display()显示每个学生的成绩。
实验数据:
No Name Math Phi Data Ave
1001 Zhou 80 70 60
1002 Chen 90 80 85
1003 Wang 70 75 89

#include<iostream>
using namespace std;

class Score{
	private:
		long long No;
		char Name[8];
		float Math;
		float Phi;
		float Data;
		float Ave;
	public:
		void Write()
		{
			cout << "Please input No. Name Math Phi Data:" << endl;
			cin >> No >> Name >> Math >> Phi >> Data; 
			Average();
		}
		void Average()
		{
			Ave = (Math + Phi + Data) / 3.0;
		}
		void Display()
		{
			cout << No << "   " << Name << "   " << Math << "   "<< Phi << "   "<< Data << "   "<< Ave << endl; 
		}
};

int main()
{
	Score s[3];
	for(int i = 0; i < 3; i++)
	{
		s[i].Write();
	} 
	cout << "No.    Name   Math Phi Data Ave" << endl;
	for(int i = 0; i < 3; i++)
	{
		s[i].Display();
	}
	return 0;
}

运行结果如下:
在这里插入图片描述

(6)

定义一个矩形类Rectangle,矩形的左上角(Left,Top)与右下角坐标(Right,Bottom)定义为保护数据成员。用公有成员函数Diagonal()计算出矩形对角线的长度,公有成员函数Show()显示矩形左上角与右下角坐标及对角线长度。在主函数中用new运算符动态建立矩形对象r1,初值为(10,10,20,20)。然后调用Show()显示矩形左上角与右下角坐标及对角线长度。最后用delete运算符回收为矩形动态分配的存储空间。

#include<bits/stdc++.h>
using namespace std;

class Rectangle{
	protected:
		int Left, Top;
		int Right, Bottom;
	public:
		Rectangle(int left, int top, int right, int bottom)
		{
			Left = left;
			Top = top;
			Right = right;
			Bottom = bottom;
		}
		float Diagonal()
		{
			int Line1 = (Left - Right) * (Left - Right);
			int Line2 = (Top - Bottom) * (Top - Bottom);
			return sqrt(Line1 + Line2);
		}
		void Show()
		{
			cout << "(" << Left << " ," << Top << ")" << endl;
			cout << "(" << Right << " ," << Bottom << ")" << endl;
			cout << Diagonal() << endl;
		}
};

int main()
{
	Rectangle *r1 = new Rectangle(10, 10, 20, 20);
	r1->Show();
	delete r1;
	return 0;
} 

运行结果如下:
在这里插入图片描述

(7)

建立一个存放素数的类Prime,具体要求如下

①私有数据成员。
int a[25]:存放指定范围内的所有素数。
int n1,n2:存放指定范围的下限和上限
int num:存放素数的个数。

②公有成员函数
Prime(int m1,int m2):构造函数,用参数m1、m2初始化n1、n2,同时初始化num。
void primef():求指定范围内的所有素数,把它们依次存放在数组a中。并将求出的素数个数赋给num。
void show():显示求出的素数的个数及所有的素数,每行输出5个素数。

③在主函数中定义一个Prime类的对象p(100,200),通过p调用成员函数完成求素数及输出素数的工作。

#include<bits/stdc++.h>
using namespace std;

class Prime{
	private:
		int a[25];
		int n1, n2;		//下限和上限 
		int num;		//存放素数个数 
	public:
		Prime(int m1, int m2)
		{
			n1 = m1;
			n2 = m2;
			num = 0;
		}
		void primef()
		{
			for(int i = n1; i <= n2; i++)
			{
				int flag = 1;
				for(int j = 2; j < sqrt(i); j++)
				{
					if(i % j == 0)
					{
						flag = 0;
						break;
					}
					else
						continue;
				}
				if(flag)
				{
					a[num++] = i;
				}
			}
		}
		void show()
		{
			cout << "Total:" << num << endl;
			for(int i = 0; i < num; i++)
			{
				cout << a[i] << " ";
				if((i + 1) % 5 == 0)
					cout << endl;
			}
			if(num >= 25)
		          cout << "数组已存满!余下的素数不存放了."<<endl;
		}
};

int main()
{
	Prime p(100, 200);
	p.primef();
	p.show();
	return 0;
}

运行结果如下:
在这里插入图片描述

之后我会持续更新,如果喜欢我的文章,请记得一键三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持!

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值