C++ 类复习题以及知识讲解

发布于:2022-11-28 ⋅ 阅读:(215) ⋅ 点赞:(0)

1.成员函数后面+const的含义。

函数后面+const即被定义成常量成员函数,常量成员函数都是只读取数据成员的值,而不会做出任何改变,并且该函数会提升程序的运行速率。

参数使用const 说明该参数在该函数中不会被更改,返回值为const说明返回值在该程序中不会被更改。

C++11新标准提供了让函数等于default将该函数直接定义为默认构造函数。

Sales_date() = default;

 2.在类的定义中对于访问说明符出现的位置和次数有限定吗?如果有,是什么?什么样的成员应该定义在public说明符之后?什么样的成员应该定义在private说明符之后?

在类的定义中, 可以包含0个或者多个访问说明符,并且对于某个访问说明符能出现多少次以及出现的位置都没有严格的规定。每个访问说明符指定接下来的成员的访问级别,有效范围直到下一个访问说明符出现或者到达了类的结尾。

一般来说,作为接口的一部分,构造函数和一部分成员函数应该定义在public说明符之后,而数据成员和作为实现部分的函数则应该跟在private说明符之后。

3.封装是何含义?它有什么用处?

封装是指保护类的成员不被随意访问的能力。通过把类的实现细节设置为private,我们就能完成类的封装。封装实现了类的接口和实现的分离。

封装有两个重要的优点:一是确保用户代码不会无意间破坏封装对象的状态;二是被封装的类的具体实现细节可以随时改变,而无须调整用户级别的代码。

一旦把数据成员定义成private的,类的作者就可以比较自由地修改数据了,当实现部分发生部分改变时,只需要检查类的代码本身以确定这次改变有什么影响:只要类的接口不变,用户代码就无须改变。如果数据是public的,则所有使用了原来数据成员的代码都将被改变。即要重写所有的代码,之后才能重新使用该程序。

4.友元在什么时候用?请分别列举出是有友元的弊端。

当非成员函数确实需要访问类的私有成员时,我们可以把它声明成该类的友元。此时,友元可以“工作在类的内部”,像类的成员一样访问类的所有数据和函数。但是一旦使用不慎(比如随意设定友元),就有可能破坏类的封装性。

5.函数的返回类型是类的引用或是类的返回值是什么?

函数的返回值如果是引用,则表明函数返回的是对象本身。返回值如果不是引用则返回的是对象的副本(临时对象)。返回引用的函数是左值,意味着这些函数返回的是对象本身而非对象的副本。

6.使用委托构造函数重新编写类,给每个构造函数添加一条语句,令其一旦执行就打印一条信息。用各种可能的方式分别创建类对象,认真的研究每一次的输出信息直到你理解了委托函数的执行顺序。 

运行的代码如下,它帮助我们去理解类的委托构造函数:

#include<iostream>
#include<string>
#include<cstdlib>
using namespace std;
class Sales_date{
	private:
		string bookNo;	//书籍编号 
		unsigned units_sold = 0;	//销售量 
		double sellingprice = 0.0;	//原始价格 
		double saleprice = 0.0;		//实售价格 
		double discount = 0.0;	//折扣 
	public:	
		friend ostream &print(ostream &os,const Sales_date &item);
		friend istream &read(istream &is, Sales_date &item);
	public:
		Sales_date(const string &book,unsigned num,double sellp,double salep)
		{
			bookNo = book;
			units_sold = num;
			sellingprice = sellp;
			saleprice = salep;
			if(sellingprice)
				discount = 1.0-saleprice/sellingprice;
			cout<<"该构造函数接受书号、销售量、原价、实际售价四个信息\n";	
		}
		Sales_date():Sales_date("", 0 ,0 ,0)
		{
			cout<<"该构造函数无序接受任何实参\n";
		}
		Sales_date(const string &book):Sales_date(book,0,0,0)
		{
			cout<<"该构造函数值接受书名的信息\n";
		}
		Sales_date(istream &is):Sales_date()
		{
			read(is,*this);
			cout<<"该构造函数使用用户输入的信息\n";
		}
};
ostream &print(ostream &os,const Sales_date &item)
{
	os<<item.bookNo<<" "<<item.units_sold<<" "<<item.sellingprice<<" "                    
     <<item.saleprice<<" "<<item.discount;
	return os;
}
istream &read(istream &is,Sales_date &item)
{
	is>>item.bookNo>>item.units_sold>>item.sellingprice>>item.saleprice;
	return is;
}
	
int main()
{
	Sales_date fist("132-190-2145",75,128,109);
	Sales_date second;
	Sales_date third("199-130-132");
	Sales_date last(cin);
	return 0;
}

该程序所运行的代码如下所示:

有上图可以了解到,委托构造函数使用它所属类的其他构造函数执行它自己初始化的过程,或者是说它把它自己的一部分职责或全部职责交给了另一个构造函数。程序限制性受委托的函数,然后才执行委托函数本身的语句,一个函数后面跟着冒号是一个初始化列表的方法可以使用该方法对成员数据进行赋值。

7.什么是类的静态成员?它有何优点?静态成员与普通成员有何区别?

 静态成员是指声明语句之前带有关键字static的类成员,静态成员不是任意对象的组成部分,而是由该类所有的对象所共享。

静态成员的优点包括:作用域位于类的范围之内,避免与其他类的成员你或者全局作用域的名字冲突;可以是私有成员,而全局成员对象不可以。

静态成员与普通成员的区别主要体现在普通成员与类的对象关联,是某个具体对象的组成部分;而静态成员从不属于任何具体的对象,它由该类的所有对象所共有,静态成员可以作为默认实参,而普通数据成员不能作为默认参数。静态常量成员可以在类中初始化,其他的静态成员不可以在类中定义初始化。

8.类的实例操作(图书馆借阅)

重载操作符一部分为友元一部分为公共类型的函数

内容如下:

	Sales_date & operator=(Sales_date &a);
	friend bool operator>(const Sales_date &a,const Sales_date &b);
	friend bool operator<(const Sales_date &a,const Sales_date &b);
	friend bool operator==(const Sales_date &a,const Sales_date &b);
	friend ostream & operator<<(ostream &os,const Sales_date &s);
	friend istream & operator>>(istream &is,Sales_date &s);
	friend int getcount(Sales_date *a,int num,double price);

具体实现的部分为:

bool operator>(const Sales_date &a,const Sales_date &b)	//重载对象图书价格大于另一个对象价格则说明这个对象大于另一个对象 
{
	return (a.saleprice > b.saleprice);
}

bool operator<(const Sales_date &a,const Sales_date &b)
{
	return (a.saleprice < b.saleprice);
}

bool operator==(const Sales_date &a,const Sales_date &b)	//判断2个图书内容是否完全相同重载= 
{   
 if(b.bookNo==a.bookNo&&b.sellingprice==a.sellingprice&&b.saleprice==a.saleprice&&b.discount==a.discount&&b.units_sold==a.units_sold) 
		return 1;
	return 0;
}

ostream & operator<<(ostream &os,const Sales_date &s)	//输出对象内容 
{
		os << s.bookNo <<" "<<s.sellingprice<<" "<<s.discount<<" "<<s.saleprice<<" "<<s.units_sold<<endl;
		return os;
}

istream & operator>>(istream &is,Sales_date &s)	//输入对象内容 
{
	cout<<"请按照书籍标号、原始价格、折扣、销售量顺序输入数据\n";
		is >> s.bookNo >> s.sellingprice>>s.discount>>s.units_sold;
		return is;
}

Sales_date & Sales_date::operator=(Sales_date &a)	//重载类对象与类对象等于的问题 
{
	bookNo=a.bookNo;
	sellingprice=a.sellingprice;
	saleprice=a.saleprice;
	discount=a.discount;
	units_sold=a.units_sold;
	return *this;				 
}

整体代码如下:

#include<iostream>
#include<string>
#include<cstdlib>
using namespace std;
int count =0; //计数 
int del=0;	//计算借走的书籍 
class Sales_date{
	private:
		string bookNo;	//书籍编号 
		unsigned units_sold = 0;	//销售量 
		double sellingprice = 0.0;	//原始价格 
		double saleprice = 0.0;		//实售价格 
		double discount = 0.0;	//折扣 
	public:
		string isbn()const {return bookNo;}	//返回书籍编号 
		Sales_date & combine(const Sales_date &r)	//当书籍编号相同时加和 
		{
			units_sold += r.units_sold;
			saleprice = (r.sellingprice*r.discount+sellingprice*discount)/(units_sold+r.units_sold);
			if(sellingprice != 0)
				discount = saleprice/sellingprice;
			return *this;
		}
		Sales_date & operator=(Sales_date &a);
		// 得到本对象的实售价格 
		Sales_date & Saleprice()
		{
			saleprice = sellingprice-sellingprice*discount;
			return *this;
		}
		void DeletebookNo(Sales_date *a,int num,string booknum,Sales_date *c)	//将书籍借阅走的函数并存入类数组c中 
		{
			int i,falg=0;
			for(i=0;i<num;i++)
			{
				if(booknum==a[i].bookNo)
				{
					falg=1;
					c[del]=a[i];
					del++;
					for(int j=i;j<num-1;j++)	//将图书馆中书籍删除 
					{	

							a[j]=a[j+1];
					}
				}
			}
			if(falg==0)
				cout<<"没有找到编号相同数据!\n";
			if(falg==1)
			{
				cout<<"下面是删除数据后的显示:\n";
				for(i=0;i<num-del;i++)
					cout<<a[i];
			}
		}
		
		void returndate(Sales_date *b,int num,Sales_date *c,int n,Sales_date *a)	//归还书籍的操作 
		{
				int flag=0;
				for(int i=0;i<num;i++)
				{
					if(c[n] == b[i])
					{
						flag=1;
					}		
				} 
				if(flag==1)
					a[num-del]=c[n];
				del--;
				if(flag==0)
					cout<<"您借走的书籍不是本图书馆的书籍!\n";	
		}
		// 友元函数定义对象之间的比较 
		friend bool operator>(const Sales_date &a,const Sales_date &b);
		friend bool operator<(const Sales_date &a,const Sales_date &b);
		friend bool operator==(const Sales_date &a,const Sales_date &b);
		friend ostream & operator<<(ostream &os,const Sales_date &s);
		friend istream & operator>>(istream &is,Sales_date &s);
		friend int getcount(Sales_date *a,int num,double price);
};

int getcount(Sales_date *a,int num,double price)	//得到与输入价格相同的数 
{
	int i;
	for(i=0;i<num;i++)
	{
		if(a[i].saleprice == price)
			count++;	
	}
	return count;	
} 

bool operator>(const Sales_date &a,const Sales_date &b)	//重载对象图书价格大于另一个对象价格则说明这个对象大于另一个对象 
{
	return (a.saleprice > b.saleprice);
}

bool operator<(const Sales_date &a,const Sales_date &b)
{
	return (a.saleprice < b.saleprice);
}

bool operator==(const Sales_date &a,const Sales_date &b)	//判断2个图书内容是否完全相同重载= 
{
	if(	b.bookNo==a.bookNo&&b.sellingprice==a.sellingprice&&b.saleprice==a.saleprice&&b.discount==a.discount&&b.units_sold==a.units_sold) 
		return 1;
	return 0;
}

Sales_date & Sales_date::operator=(Sales_date &a)	//重载类对象与类对象等于的问题 
{
	bookNo=a.bookNo;
	sellingprice=a.sellingprice;
	saleprice=a.saleprice;
	discount=a.discount;
	units_sold=a.units_sold;
	return *this;				 
}

//因为一个对象在操作符的左边一个在右边且不想使用对象调用函数则可以使用友元函数 
ostream & operator<<(ostream &os,const Sales_date &s)	//输出对象内容 
{
		os << s.bookNo <<" "<<s.sellingprice<<" "<<s.discount<<" "<<s.saleprice<<" "<<s.units_sold<<endl;
		return os;
}

istream & operator>>(istream &is,Sales_date &s)	//输入对象内容 
{
	cout<<"请按照书籍标号、原始价格、折扣、销售量顺序输入数据\n";
		is >> s.bookNo >> s.sellingprice>>s.discount>>s.units_sold;
		return is;
}


int main()
{
	Sales_date a[20],c[20],b[20],x;	//a为图书馆本来存储的书籍,c为用户借走要归还的书籍 
	string booknum;
	int num;
	double price=0.0;
	char ch;
	cout<<"请输入对象的个数:\n";
	cin>>num;
	for(int j=0;j<num;j++)
	{
		cin>>a[j];
		a[j].Saleprice();
	}
	for(int j=0;j<num;j++)
		b[j]=a[j];
	cout<<"下面是您输入的数据展示:\n";
	cout<<"输出顺序为图书编号、原价、折扣、现售价和销售量\n";
	for(int k=0;k<num;k++)
		cout<<a[k];
	cout<<"您是否要使用价格查找功能\n";
	cin>>ch;
	if(ch == 'y'||ch == 'Y')
	{
		cout<<"请输入您要找的价格:\n";
		cin>>price;
		cout<<"与您要找价格相同的图书有"<<getcount(a,num,price)<<"本\n";
	}
	cout<<"您是否要使用借阅书籍的功能\n";
	cin>>ch;
	if(ch == 'y'||ch == 'Y')
	{
		int i=0;
		cout<<"您要借走几本图书->";
		cin>>i;
		for(int j=0;j<i;j++)
		{
			cout<<"请输入您要借走的图书编号:\n";
			cin>>booknum;
			x.DeletebookNo(a,num,booknum,c);
		}	
	}
	cout<<"您借走的书籍如下:\n";
	for(int i=0;i<del;i++)
		cout<<c[i];	
	cout<<"您是否要归还书籍\n";
	cin>>ch;
	if(ch == 'y'||ch == 'Y')
	{ 
		int i=0;
		cout<<"请输入您归还书籍的个数->\n";
		cin>>i;
		for(int j=0;j<i;j++)
			x.returndate(b,num,c,j,a);
		cout<<"归还之后的图书馆内图书和您借走的书籍如下:\n";
		for(int i=0;i<num-del;i++)
			cout<<a[i];
		if(del>0)
		{
			for(int i=0;i<del;i++)
				cout<<c[i];
		}
		else
			cout<<"您所借的书籍均已归还!";
	} 
	return 0;
}

运行结果如下图所示:

 

 

 该程序可能还有一些问题没有完善,本篇内容就到这了详细类的复习在相关专栏里也有可以看看

本文含有隐藏内容,请 开通VIP 后查看