深圳大学计软《面向对象的程序设计》实验12 虚函数与多态

A. 汽车收费(虚函数和多态)

题目描述

现在要开发一个系统,实现对多种汽车的收费工作。 汽车基类框架如下所示:

class Vehicle

{ protected:

string no;//编号

public:

virtual void display()=0;//应收费用

}

以Vehicle为基类,构建出Car、Truck和Bus三个类。

Car的收费公式为: 载客数8+重量2

Truck的收费公式为:重量*5

Bus的收费公式为: 载客数*3

生成上述类并编写主函数,要求主函数中有一个基类指针Vehicle *pv;用来做测试用。

主函数根据输入的信息,相应建立Car,Truck或Bus类对象,对于Car给出载客数和重量,Truck给出重量,Bus给出载客数。假设载客数和重量均为整数。

输入

第一行表示测试次数。从第二行开始,每个测试用例占一行,每行数据意义如下:汽车类型(1为car,2为Truck,3为Bus)、编号、基本信息(Car是载客数和重量,Truck给出重量,Bus给出载客数)。

输出

车的编号、应缴费用

输入样例1

4
1 002 20 5
3 009 30
2 003 50
1 010 17 6

输出样例1

002 170
009 90
003 250
010 148

AC代码

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

class Vehicle {
    
    

protected:
	string no;//编号
public:
	virtual void display() = 0;
	Vehicle(string no) :no(no) {
    
    }
};

class Car :public Vehicle {
    
    
	int seat, weight;
public:
	Car(string no, int seat, int weight) :
		Vehicle(no), seat(seat), weight(weight)
	{
    
    }

	void display() {
    
    
		cout << no << " ";
		cout << seat * 8 + weight * 2 << endl;
	}
};


class Truck :public Vehicle {
    
    
	int weight;
public:
	Truck(string no, int weight) :
		Vehicle(no), weight(weight)
	{
    
    }

	void display() {
    
    
		cout << no << " ";
		cout << weight * 5 << endl;
	}
};

class Bus :public Vehicle {
    
    
	int seat;
public:
	Bus(string no, int seat) :
		Vehicle(no), seat(seat)
	{
    
    }

	void display() {
    
    
		cout << no << " ";
		cout << seat * 3 << endl;
	}
};


int main() {
    
    
	int t;
	cin >> t;
	while (t--) {
    
    
		int type;
		cin >> type;
		Vehicle* pv;
		if (type == 1) {
    
    
			string no;
			int a, b;
			cin >> no >> a >> b;
			Car c(no, a, b);
			pv = &c;
			pv->display();
		}
		else if (type == 2) {
    
    
			string no;
			int a;
			cin >> no >> a;
			Truck tr(no, a);
			pv = &tr;
			pv->display();
		}
		else {
    
    
			string no;
			int a;
			cin >> no >> a;
			Bus b(no, a);
			pv = &b;
			pv->display();
		}

	}
	return 0;
}

B. 动物园(虚函数与多态)

题目描述

某个动物园内,有老虎、狗、鸭子和猪等动物,动物园的管理员为每个动物都起了一个名字,并且每个动物都有年龄、体重等信息。每到喂食的时候,不同的动物都会叫唤(speak)。每种动物的叫唤声均不同,老虎的叫唤声是“AOOO”,狗的叫唤声是“WangWang”,鸭子的叫唤声是“GAGA”,猪的叫唤声是“HENGHENG”。

定义一个Animal的基类,Animal类有函数Speak(),并派生老虎(Tiger)、狗(Dog)、鸭子(Duck)和猪(Pig)类,其能发出不同的叫唤声(用文本信息输出叫声)。

编写程序,输入动物名称、名字、年龄,让动物园内的各种动物叫唤。

要求:只使用一个基类指针,指向生成的对象并调用方法。

输入

测试案例的个数

第一种动物的名称 名字 年龄

第二种动物的名称 名字 年龄

输出

输出相应动物的信息

如果不存在该种动物,输出There is no 动物名称 in our Zoo. ,具体输出参考样例输出

输入样例1

4
Tiger Jumpjump 10
Pig Piglet 4
Rabbit labi 3
Duck tanglaoya 8

输出样例1

Hello,I am Jumpjump,AOOO.
Hello,I am Piglet,HENGHENG.
There is no Rabbit in our Zoo.
Hello,I am tanglaoya,GAGA.

AC代码

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

class Animal {
    
    

protected:
	string name;
	int age;
public:
	virtual void speak() = 0;
	Animal(string name, int age) :name(name), age(age) {
    
    }
};

class Tiger :public Animal {
    
    
public:
	Tiger(string name, int age) :
		Animal(name, age)
	{
    
    }

	void speak() {
    
    
		cout << "Hello,I am " << name << ",";
		cout << "AOOO." << endl;
	}
};


class Dog :public Animal {
    
    
public:
	Dog(string name, int age) :
		Animal(name, age)
	{
    
    }

	void speak() {
    
    
		cout << "Hello,I am " << name << ",";
		cout << "WangWang." << endl;
	}
};

class Duck :public Animal {
    
    
public:
	Duck(string name, int age) :
		Animal(name, age)
	{
    
    }

	void speak() {
    
    
		cout << "Hello,I am " << name << ",";
		cout << "GAGA." << endl;
	}
};



class Pig :public Animal {
    
    
public:
	Pig(string name, int age) :
		Animal(name, age)
	{
    
    }

	void speak() {
    
    
		cout << "Hello,I am " << name << ",";
		cout << "HENGHENG." << endl;
	}
};

int main() {
    
    
	int t;
	cin >> t;

	while (t--) {
    
    
		string type;
		cin >> type;
		string s;
		int a;
		cin >> s >> a;
		Animal* pv;

		if (type == "Tiger") {
    
    
			Tiger c(s, a);
			pv = &c;
			pv->speak();
		}
		else if (type == "Pig") {
    
    
			Pig p(s, a);
			pv = &p;
			pv->speak();
		}
		else if (type == "Duck") {
    
    
			Duck d(s, a);
			pv = &d;
			pv->speak();
		}
		else if (type == "Dog") {
    
    
			Dog d(s, a);
			pv = &d;
			pv->speak();
		}
		else cout << "There is no " << type << " in our Zoo." << endl;
	}
	return 0;
}

C. 支票账户(虚函数与多态)

题目描述

某银行的支票账户分为两类,一类为基本支票账户BaseAccount,另一类为具有透支保护特性的BasePlus支票账户。

BaseAccount支票账户的信息包括:客户姓名(name)、账户(account)、当前结余(balance);BaseAccount支票账户可以执行的操作包括:存款(deposit)、取款(withdraw)、显示账户信息(display)。注意:取款金额不能透支,否则显式出错信息“insufficient”。

BasePlus支票账户除包含BaseAccount的所有信息外,还包括以下信息:透支上限(limit:默认为5000),当前透支总额(limit_sum);BasePlus支票账户可执行的操作与BaseAccount相同,但有两种操作的实现不同:(1)对于取款操作,可以在透支上限范围内透支,超过则显示出错信息“insufficient”;(2)对于显示操作,必须显示BasePlus的其他信息。

请实现BaseAccount类和BasePlus类,其中BasePlus类继承于BaseAccount类,注意BaseAccount账户名称以BA开头,BasePlus账户名称以BP开头。

要求只使用一个基类指针,指向所建立的对象,然后使用指针调用类中的方法。

输入

测试案例组数 t

第一组测试数据:

第一行输入账户信息:姓名 帐号 当前余额

第二行输入四个整数,表示对账户按顺序存款、取款、存款、取款

第二组测试数据:

输出

输出BaseAccount的信息

输出BasePlus的信息

输入样例1

4
Tom BA008 1000
1000 2000 1000 1200
Bob BP009 1000
1000 2000 1000 7000
May BA001 2000
500 1000 500 1000
Lily BP002 1000
500 2000 500 3000

输出样例1

insufficient
Tom BA008 Balance:1000
insufficient
Bob BP009 Balance:1000 limit:5000
May BA001 Balance:1000
Lily BP002 Balance:0 limit:2000

AC代码

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

class BaseAccount {
    
    
protected:
	string name, account;
	int balance;
public:
	BaseAccount(string name, string account, int balance) :
		name(name),
		account(account),
		balance(balance) {
    
    }

	virtual void deposit(int v) {
    
    
		balance += v;
	}

	virtual void withdraw(int v) {
    
    
		if (v > balance) {
    
    
			cout << "insufficient" << endl;
			return;
		}
		balance -= v;
	}

	virtual void display() {
    
    
		cout << name << " " << account << " " << "Balance:" << balance << endl;
	}

};

class BasePlus :public BaseAccount {
    
    
	const int limit;
	int limit_sum;//当前透支总额
public:
	BasePlus(string name, string account, int balance) :
		limit(5000),
		BaseAccount(name, account, balance),
		limit_sum(0)
	{
    
    }

	virtual void display() {
    
    
		cout << name << " " << account << " " << "Balance:" << balance << " ";
		cout << "limit:" << limit - limit_sum << endl;
	}

	virtual void deposit(int v) {
    
    
		if (limit_sum > 0) {
    
    
			limit_sum -= v;
			if (limit_sum < 0) {
    
    
				balance -= limit_sum;
				limit_sum = 0;
			}
		}
		else {
    
    
			balance += v;
		}

	}

	virtual void withdraw(int v) {
    
    
			if (v > balance + limit - limit_sum) {
    
    
				cout << "insufficient" << endl;
				return;
			}

			if (balance==0) {
    
    
				limit_sum += v;
			}
			else {
    
    
				limit_sum += v - balance;
				balance = 0;
			}
	}
};


int main() {
    
    
	int t;
	cin >> t;
	BaseAccount* p;
	while (t--) {
    
    
		string s1, s2;
		int balance;
		cin >> s1 >> s2 >> balance;
		if (s2[1] == 'P') {
    
    
			BasePlus b(s1, s2, balance);
			p = &b;
			int a, b1, c, d;
			cin >> a >> b1 >> c >> d;
			p->deposit(a);
			p->withdraw(b1);
			p->deposit(c);
			p->withdraw(d);
			p->display();
		}
		else {
    
    
			BaseAccount b(s1, s2, balance);
			p = &b;
			int a, b1, c, d;
			cin >> a >> b1 >> c >> d;
			p->deposit(a);
			p->withdraw(b1);
			p->deposit(c);
			p->withdraw(d);
			p->display();
		}
	}
	return 0;
}

D. 求最大面积(虚函数和多态)

题目描述

请编写程序,从图形数组中找出最大面积。基类框架如下所示:

class Geometry{

public:

virtual double getArea()=0; //计算面积,结果保留小数点后两位

};

以Geometry为基类,构建出Rect(矩形,数据成员为长和宽)和Circle(圆,数据成员为半径)两个类,重写getArea()方法,其他方法根据需要自拟。

写一个TotalArea类,该类结构如下:

class TotalArea{

public:

static void computerMaxArea(Geometry** t,int n);//t为基类二级指针,指向一个基类动态数组,数组的每个元素指向一个子类图形,n为数组的大小

};

生成上述四个类并编写主函数,结果保留两位小数。

输入

第一行表示测试次数。从第二行开始,每个测试用例占一行,每行数据意义如下:图形类型(1为Rect(矩形),2为Circle(圆))、基本信息(Rect是长和宽,Circle是半径)。

输出

最大图形的面积

输入样例1

3
1 3 4
2 5
2 6

输出样例1

最大面积=113.04

AC代码

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

class Geometry {
    
    

public:
	virtual double getArea() = 0; //计算面积,结果保留小数点后两位
};


class Rect : public Geometry {
    
    
	double a, b;
public:
	Rect(double a = 0, double b = 0) :a(a), b(b) {
    
    }
	double getArea() {
    
     return a * b; }
};

class Circle :public Geometry {
    
    
	double r;
public:
	Circle(double r = 0) :r(r) {
    
    }
	double getArea() {
    
     return 3.14 * r * r; }
};


class TotalArea {
    
    
public:
	static void computerTotalArea(Geometry** t, int n) {
    
    
		sort(t, t + n, [](Geometry* g1, Geometry* g2) {
    
    
			return g1->getArea() > g2->getArea();
			});
		cout << "最大面积=" << fixed << setprecision(2) << (*t)->getArea() << endl;
	}
};

int main() {
    
    
	int n;
	cin >> n;
	Geometry** p = new Geometry * [n];
	for (int i = 0; i < n; i++) {
    
    
		int t;
		cin >> t;
		if (t == 1) {
    
    
			int a, b;
			cin >> a >> b;
			p[i] = new Rect(a, b);
		}
		else {
    
    
			int r;
			cin >> r;
			p[i] = new Circle(r);
		}
	}

	TotalArea::computerTotalArea(p, n);

	for (int i = 0; i < n; i++) {
    
    
		delete[]p[i];
	}delete[]p;
	return 0;
}

E. 宠物的生长(虚函数和多态)

题目描述

需要开发一个系统,对宠物的生长状态进行管理。给出下面的基类框架:

class Pet

{ protected:

string name;//姓名

int length;//身长

int weight;//体重

CDatecurrent;//开始记录时间

(日期类CDate包含年、月、日三个私有数据,其他方法根据需要自拟。)

public:

virtual void display(CDate day)=0;//输出目标日期时宠物的身长和体重

}

以Pet为基类,构建出Cat和Dog两个类:

Cat一天身长加0.1,体重加0.2。

Dog一天身长加0.2,体重加0.1。

生成上述类并编写主函数,要求主函数中有一个基类指针Pet *pt,用于测试子类数据。

主函数根据输入的信息,相应建立Cat类对象或Dog类对象,并给出测量日期时宠物的身长和体重。

输入

第一行为测试次数

第二行是开始记录日期

从第三行起,每个测试用例占一行,每行给出宠物的基本信息:宠物的类型(1为Cat,2为Dog)、名字、身长、体重、最后测量的日期。

输出

要求输出目标日期宠物姓名、身长和体重(结果要求保留小数点后2位)。若测量日期小于开始日期,输出”error”。

输入样例1

3
2019 5 5
1 tony 10 10 2018 12 30
2 jerry 5 6 2019 5 10
1 tom 3 4 2019 6 1

输出样例1

error
jerry after 5 day: length=6.00,weight=6.50
tom after 27 day: length=5.70,weight=9.40

AC代码

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

class CDate {
    
    
	int year, month, day;
public:
	CDate(int y, int m, int d) :
		year(y),
		month(m),
		day(d)
	{
    
    }

	bool operator <(const CDate& c)const {
    
    
		if (year != c.year)
			return year < c.year;
		if (month != c.month)
			return month < c.month;
		if (day != c.day)
			return day < c.day;
	}

	bool operator ==(const CDate& c)const {
    
    
		return year == c.year && month == c.month && day == c.day;
	}

	CDate getTomorrow() {
    
    
		int days[] = {
    
     31,28,31,30,31,30,31,31,30,31,30,31 };
		if (year % 400 || (year % 4 == 0 && year % 100 != 0))
			days[1]++;
		CDate date = *this;

		date.day++;
		if (date.day > days[date.month - 1]) {
    
    
			date.month++;
			date.day = 1;
		}

		if (date.month > 12) {
    
    
			date.month = 0;
			date.year++;
		}
		return date;
	}

	int getDays(const CDate& date) {
    
    
		if (*this < date)
			return -1;
		CDate today = date;
		int cnt = 0;
		do
		{
    
    
			today = today.getTomorrow();
			cnt++;
		} while (!(today == *this));
		return cnt;
	}

};

class Pet {
    
    
protected:
	string name;//姓名
	int length;//身长
	int weight;//体重
	CDate current;//开始记录时间
public:
	Pet(string n, int l, int w, CDate c) :
		name(n),
		length(l),
		weight(w),
		current(c)
	{
    
    }

	virtual void display(CDate day) = 0;//输出目标日期时宠物的身长和体重

};


class Cat :public Pet {
    
    
public:
	Cat(string n, int l, int w, CDate c) :
		Pet(n, l, w, c)
	{
    
    }

	void display(CDate day) {
    
    
		int t = current.getDays(day);
		if (t == -1) {
    
    
			cout << "error" << endl;
			return;
		}
		cout << name << " after " << t << " day: ";
		cout << "length=" << fixed << setprecision(2) << length + t * 0.1 << ",weight=" << weight + t * 0.2 << endl;
	}
};


class Dog :public Pet {
    
    
public:
	Dog(string n, int l, int w, CDate c) :
		Pet(n, l, w, c)
	{
    
    }

	void display(CDate day) {
    
    
		int t = current.getDays(day);
		if (t == -1) {
    
    
			cout << "error" << endl;
			return;
		}
		cout << name << " after " << t << " day: ";
		cout << "length=" << fixed << setprecision(2) << length + t * 0.2 << ",weight=" << weight + t * 0.1 << endl;
	}
};

int main() {
    
    
	Pet* pt;
	int t;
	cin >> t;
	int y, m, d;
	cin >> y >> m >> d;
	CDate des(y, m, d);
	while (t--) {
    
    
		int type;
		string name;
		int a, b, c, d1, e;;
		cin >> type >> name >> a >> b >> c >> d1 >> e ;

		if (type == 1) {
    
    
			pt = new Cat(name, a, b, CDate(c, d1, e));
		}
		else pt = new Dog(name, a, b, CDate(c, d1, e));
		pt->display(des);
	}
	return 0;
}

F. 进位与借位(虚函数和多态)

题目描述

某小学二年级的数学老师在教学生整数加减法运算时发现:班上的同学可以分成三类,第一类可以正确地完成加减法运算(GroupA);第二类可以正确地完成加法运算,但对于减法运算来说,总是忘记借位的处理(GroupB);第三类总是忘记加法的进位,也总是忘记减法的借位(GroupC)。(提示:小学二年级还没学负数。)

现在请模拟当老师在课堂提问某位同学时,同学会给出的回答。

实现时请基于下面的基类框架:

class Group

{

public:

virtual int add(int x, int y)=0;//输出加法的运算结果

virtual int sub(int x, int y)=0;//输出减法的运算结果

}

构建出GroupA, GroupB和GroupC三个派出类:

并编写主函数,要求主函数中有一个基类Group指针,通过该指针统一地进行add和sub运算。

输入

第一行表示测试次数。从第二行开始,每个测试用例占一行,每行数据意义如下:学生类别(1为第一类学生,2为第二类学生,3为第三类学生)、第一个数、第二个数。

输出

运算后的结果

输入样例1

3
1 79+81
2 81-79
3 183+69

输出样例1

160
12
142

AC代码

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

class Group
{
    
    
public:
	virtual int add(int x, int y) = 0;//输出加法的运算结果
	virtual int sub(int x, int y) = 0;//输出减法的运算结果
};

//GroupA, GroupB和GroupC
class GroupA :public Group {
    
    
public:
	int add(int x, int y) {
    
     return x + y; }
	int sub(int x, int y) {
    
     return x - y; }
};

class GroupB :public Group {
    
    
	int add(int x, int y) {
    
     return x + y; }  //√

	int sub(int x, int y) {
    
    
		string a = to_string(x);
		string b = to_string(y);
		while (a.length() < b.length())
			a = "0" + a;
		while (a.length() > b.length())
			b = "0" + b;

		string c;
		for (int i = 0; i < a.length(); i++) {
    
    
			int temp = a[i] - b[i];
			if (temp < 0)
				temp += 10;
			c += temp + '0';
		}

		int ans = stoi(c);
		return ans;
	}
};

class GroupC :public Group {
    
    

	int sub(int x, int y) {
    
    
		string a = to_string(x);
		string b = to_string(y);
		while (a.length() < b.length())
			a = "0" + a;
		while (a.length() > b.length())
			b = "0" + b;

		string c;
		for (int i = 0; i < a.length(); i++) {
    
    
			int temp = a[i] - b[i];
			if (temp < 0)
				temp += 10;
			c += temp + '0';
		}

		int ans = stoi(c);
		return ans;
	}


	int add(int x, int y) {
    
    
		string a = to_string(x);
		string b = to_string(y);
		while (a.length() < b.length())
			a = "0" + a;
		while (a.length() > b.length())
			b = "0" + b;

		string c;

		for (int i = 0; i < a.length(); i++) {
    
    
			int temp = a[i] - '0' + b[i] - '0';
			if (temp > 10)
				temp -= 10;
			c += ('0' + temp);
		}

		int ans = stoi(c);
		return ans;

	}
};

int main() {
    
    
	Group* p;

	int t;
	cin >> t;
	while (t--)
	{
    
    
		int t, a, b;
		char c;
		cin >> t >> a >> c >> b;
		if (t == 1) {
    
    
			p = new GroupA;
			if (c == '+')
				cout << p->add(a, b) << endl;
			else
				cout << p->sub(a, b) << endl;
		}
		else if (t == 2) {
    
    
			p = new GroupB;
			if (c == '+')
				cout << p->add(a, b) << endl;
			else
				cout << p->sub(a, b) << endl;
		}
		else {
    
    
			p = new GroupC;
			if (c == '+')
				cout << p->add(a, b) << endl;
			else
				cout << p->sub(a, b) << endl;
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_46655675/article/details/129325919