题目一:员工工资(虚函数与多态)
题目描述:
某公司员工的属性有:姓名、职位、级别、工作年限,级别和年限都是非负整数,否则显示错误。包含方法有:构造函数,计算工资的方法(salary())。
员工职位分为三种:Employee、Teamleader、Manager,其他职位类型显示错误。
三种职位员工的区别在于计算工资的方法不同:
1. Employee的每月工资 = 1000 + 500*级别 + 50*工作年限
2. Teamleader的每月工资 = 3000 + 800*级别 + 100*工作年限
3. Manager的每月工资 = 5000 + 1000 * (级别+工作年限)
计算工资的方法返回每个员工的工资数。
要求:以普通员工为基类,组长和经理继承基类,程序中只能使用基类指针指向对象与调用对象的方法。
输入要求:
测试案例的个数 t
每行输入一个员工的信息:包括姓名、职位、级别、工作年限
输出要求:
输出相应员工的信息
如有错误信息,则输出错误信息,若职位信息与级别和年限信息同时出错,仅输出职位错误信息
输入样例:
5
zhangsan Employee 4 5
lisi Teamleader 4 5
Wangwu Manager 4 5
chenliu Precident 4 5
xiaoxiao Manager -1 5
输出样例:
zhangsan:Employee,Salary:3250
lisi:Teamleader,Salary:6700
Wangwu:Manager,Salary:14000
error position.
error grade or year.
代码示例:
#include
#include
#include
#include
#include
#include
using namespace std;
class Staff
{
protected:
string name, post;
int year, level;
public:
Staff() {}
Staff(string nn, string pp, int yy, int ll) :name(nn), post(pp), year(yy), level(ll) {}
virtual int getSalary()
{
return 0;
}
virtual void display() {}
};
class Employee :public Staff
{
public:
Employee() {}
Employee(string nn, string pp, int yy, int ll) :Staff(nn, pp, yy, ll) {}
virtual int getSalary()
{
return 1000 + 500 * level + 50 * year;
}
virtual void display()
{
cout << name << ":Employee,Salary:" << getSalary() << endl;
}
};
class Teamleader : public Staff
{
public:
Teamleader() {}
Teamleader(string nn, string pp, int yy, int ll) :Staff(nn, pp, yy, ll) {}
virtual int getSalary()
{
return 3000 + 800 * level + 100 * year;
}
virtual void display()
{
cout << name << ":Teamleader,Salary:" << getSalary() << endl;
}
};
class Manager :public Staff
{
public:
Manager() {}
Manager(string nn, string pp, int yy, int ll) :Staff(nn, pp, yy, ll) {}
virtual int getSalary()
{
return 5000 + 1000 * level + 1000 * year;
}
virtual void display()
{
cout << name << ":Manager,Salary:" << getSalary() << endl;
}
};
int main()
{
int t;
cin >> t;
Staff* s;//用基类指针指向对象与调用对象的方法
while (t--)
{
string na, po;
int lv, ye;
cin >> na >> po >> lv >> ye;
if (po != "Manager" && po != "Teamleader" && po != "Employee")
{
cout << "error position." << endl;
}
else if (lv < 0 || ye < 0)
{
cout << "error grade or year." << endl;
}
else
{
if (po == "Employee")
{
Employee e(na, po, ye, lv);
s = &e;//指针指向对象
s->display();//调用对象,下面同理
}
else if (po == "Teamleader")
{
Teamleader t(na, po, ye, lv);
s = &t;
s->display();
}
else if (po == "Manager")
{
Manager m(na, po, ye, lv);
s = &m;
s->display();
}
}
}
return 0;
}
掌握基类指针指向对象与调用对象的方法!!
题目二:支票账户(虚函数与多态)
题目描述:
某银行的支票账户分为两类,一类为基本支票账户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的信息
输入样例:
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
输出样例:
insufficient
Tom BA008 Balance:1000
insufficient
Bob BP009 Balance:1000 limit:5000
May BA001 Balance:1000
Lily BP002 Balance:0 limit:2000
代码示例:
#include
#include
#include
#include
#include
#include
using namespace std;
class BaseAccount
{
protected:
string name, account;
int balance;
public:
BaseAccount() :balance(0) {}
BaseAccount(string nn, string aa, int bb) :name(nn), account(aa), balance(bb) {}
void deposit(int dd)
{
balance = balance + dd;
}
void virtual withdraw(int ww)
{
if (ww > balance)
{
cout << "insufficient" << endl;
}
else
{
balance -= ww;
}
}
void virtual display()
{
cout << name << " " << account << " Balance:" << balance << endl;
}
};
class BasePlus :public BaseAccount
{
int limit;
int limitsum;
public:
BasePlus() :limit(5000) {}
BasePlus(string nn, string aa, int bb) :BaseAccount(nn, aa, bb), limit(5000) {}
void withdraw(int ww)
{
if (ww > (balance + limit))
cout << "insufficient" << endl;
else
{
if (ww > balance)
{
limit -= ww - balance;
balance = 0;
}
else
{
balance -= ww;
}
}
}
void display()
{
cout << name << " " << account << " Balance:" << balance << " limit:" << limit << endl;
}
};
int main()
{
int t;
cin >> t;
while (t--)
{
string na, ac;
int ba;
int d1, d2, w1, w2;
BaseAccount* p;
cin >> na >> ac >> ba;
string a[6];
a[1] = ac[1];//将字符串中的第1个字符赋值给另一个字符串的方法
if (a[1] == "A")
{
p = new BaseAccount(na, ac, ba);//使用一个基类指针,指向所建立的对象,然后使用指针调用类中的第二种方法
cin >> d1 >> w1 >> d2 >> w2;
p->deposit(d1);
p->withdraw(w1);
p->deposit(d2);
p->withdraw(w2);
p->display();
}
else if (a[1] == "P")
{
p = new BasePlus(na, ac, ba);
cin >> d1 >> w1 >> d2 >> w2;
p->deposit(d1);
p->withdraw(w1);
p->deposit(d2);
p->withdraw(w2);
p->display();
}
}
return 0;
}
注意使用一个基类指针,指向所建立的对象,然后使用指针调用类中的第二种方法。
题目三:计算宝宝帐户收益(多重继承)
题目描述:
定义一个类CPeople,具有身份号码(id,char[20])和姓名(name,char[10])两个数据成员,从CPeople类中再派生出CInternetUser类和CBankCustomer类,然后再从CInternetUser和CBankCustomer多重继承派生出CInternetBankCustomer类。
CInternetUser类有登录密码(password,char[20])属性和注册register(设置id, name和password),登录login(判断输入的id与password是否与对象注册的相同)成员函数。
CBankCustomer类有余额(balance,double)属性和开户openAccount(设置客户姓名和id),存款deposit,取款withdraw以及缺省的构造函数。
CInternetBankCustomer类包括有余额, 前一日余额, 当日收益,今日万元收益和上一日万元收益等5个数据成员,成员函数有缺省构造函数,存款和取款,设置万元收益,计算当日收益,登陆login(判断输入的id和密码是否与互联网用户的相同,同时从CBankCustomer继承的用户姓名和id要与从CInternetUser继承的相同)。CInternetBankCustomer类对象当日存款不计算收益,第2天开始才能计算收益,当日取款部分无收益。
可参照如下所示的主函数来测试并设计输入数据:
void main()
{
int t, no_of_days, i;
char i_xm[20], i_id[20], i_mm[20], b_xm[20], b_id[20], ib_id[20], ib_mm[20];
double money, interest;
char op_code;
//输入测试案例数t
cin >> t;
while (t--)
{
//输入互联网用户注册时的用户名,id,登陆密码
cin >> i_xm >> i_id >> i_mm;
//输入银行开户用户名,id
cin >> b_xm >> b_id;
//输入互联网用户登陆时的id,登陆密码
cin >> ib_id >> ib_mm;
CInternetBankCustomer ib_user;
ib_user.registerUser(i_xm, i_id, i_mm);
ib_user.openAccount(b_xm, b_id);
if (ib_user.login(ib_id, ib_mm) == 0) //互联网用户登陆,若id与密码不符;以及银行开户姓名和id与互联网开户姓名和id不同
{
cout << "Password or ID incorrect" << endl;
continue;
}
//输入天数
cin >> no_of_days;
for (i=0; i < no_of_days; i++)
{
//输入操作代码, 金额, 当日万元收益
cin >> op_code >> money >> interest;
switch (op_code)
{
case 'S': //从银行向互联网金融帐户存入
case 's':
if (ib_user.deposit(money) == 0)
{
cout << "Bank balance not enough" << endl;
continue;
}
break;
case 'T': //从互联网金融转入银行帐户
case 't':
if (ib_user.withdraw(money) == 0)
{
cout << "Internet bank balance not enough" << endl;
continue;
}
break;
case 'D': //直接向银行帐户存款
case 'd':
ib_user.CBankCustomer::deposit(money);
break;
case 'W': //直接从银行帐户取款
case 'w':
if (ib_user.CBankCustomer::withdraw(money) == 0)
{
cout << "Bank balance not enough" << endl;
continue;
}
break;
default:
cout << "Illegal input" << endl;
continue;
}
ib_user.setInterest(interest);
ib_user.calculateProfit();
//输出用户名,id
//输出银行余额
//输出互联网金融账户余额
ib_user.print();
}
}
}
输入要求:
输入用户例数
输入第1个互联网用户注册时的用户名,id,登陆密码
输入第1个用户银行开户用户名,id
输入第1个互联网用户登陆时的id,登陆密码
输入第1个用户操作天数
循环输入操作代码(S,T,D,W) 金额 当日万元收益
......
输出要求:
输出第1个用户名,id
输出第1个用户银行余额
输出第1个互联网金融账户余额
......
输入样例:
2
zhangsan 1234567890 222222
zhangsan 1234567890
1234567890 222222
4
D 15000 0
s 8000 1.5
T 3000 1.55
w 2000 0
lisi 2014150000 abcdef
lisi 2014150000
2014150000 123456
输出样例:
Name: zhangsan ID: 1234567890
Bank balance: 15000
Internet bank balance: 0
Name: zhangsan ID: 1234567890
Bank balance: 7000
Internet bank balance: 8000
Name: zhangsan ID: 1234567890
Bank balance: 10000
Internet bank balance: 5001.2
Name: zhangsan ID: 1234567890
Bank balance: 8000
Internet bank balance: 5001.98
Password or ID incorrect
代码示例:
#include
#include
#include
#include
#include
#include
using namespace std;
class People
{
protected:
char id[20], name[10];
public:
People() {}
People(char nn[10], char ii[20])
{
strcpy(name, nn);
strcpy(id, ii);
}
};
class InternetUser :virtual public People
{
protected:
char password[20];
public:
InternetUser() {}
InternetUser(char nn[10], char ii[20], char pp[20]) :People(nn, ii)
{
strcpy(password, pp);
}
void Register(char nn[10], char ii[20], char pp[20])
{
strcpy(name, nn);
strcpy(id, ii);
strcpy(password, pp);
}
};
class BankCustomer :virtual public People
{
protected:
double balance;
public:
BankCustomer() {}
void openAccount(char nn[10], char ii[20])
{
strcpy(name, nn);
strcpy(id, ii);
balance = 0;
}
void Deposit(double dd)
{
balance += dd;
}
int Withdraw(double ww)
{
if (balance - ww >= 0)
{
balance -= ww;
return 1;
}
else
{
return 0;
}
}
};
class InternetBankCustomer :public InternetUser, public BankCustomer
{
protected:
double balancei, balancey, profit, profitp, profity;
public:
InternetBankCustomer()
{
balancei = 0.00;
balancey = 0.00;
profit = 0.00;
profitp = 0.00;
profity = 0.00;
}
int Login(char ii[20], char pp[20])
{
return ((!strcmp(ii, InternetUser::id)) && (!strcmp(pp, InternetUser::password))) && (!strcmp(InternetUser::id, BankCustomer::id) && !strcmp(InternetUser::name, BankCustomer::name));
}
int Deposit(double dd)
{
if (balance - dd >= 0)
{
balance -= dd;
balancei += dd;
return 1;
}
else
{
return 0;
}
}
int Withdraw(double ww)
{
if (balancei - ww >= 0)
{
balancei -= ww;
balance += ww;
return 1;
}
else
{
return 0;
}
}
void setInterest(double ii)
{
profity = profitp;
profitp = ii;
}
void calculateProfit()
{
profit = profity * 0.0001 * balancey;
balancei += profit;
balancey = balancei;
}
void print()
{
cout << "Name: " << BankCustomer::name << " ID: " << BankCustomer::id << endl;
cout << "Bank balance: " << balance << endl;
cout << "Internet bank balance: " << balancei << endl;
cout << endl;
}
};
int main()
{
int t, no_of_days, i;
char i_xm[20], i_id[20], i_mm[20], b_xm[20], b_id[20], ib_id[20], ib_mm[20];
double money, interest;
char op_code;
//输入测试案例数t
cin >> t;
while (t--)
{
//输入互联网用户注册时的用户名,id,登陆密码
cin >> i_xm >> i_id >> i_mm;
//输入银行开户用户名,id
cin >> b_xm >> b_id;
//输入互联网用户登陆时的id,登陆密码
cin >> ib_id >> ib_mm;
InternetBankCustomer ib_user;
ib_user.Register(i_xm, i_id, i_mm);
ib_user.openAccount(b_xm, b_id);
if (ib_user.Login(ib_id, ib_mm) == 0) //互联网用户登陆,若id与密码不符;以及银行开户姓名和id与互联网开户姓名和id不同
{
cout << "Password or ID incorrect" << endl;
continue;
}
//输入天数
cin >> no_of_days;
for (i = 0; i < no_of_days; i++)
{
//输入操作代码, 金额, 当日万元收益
cin >> op_code >> money >> interest;
switch (op_code)
{
case 'S': //从银行向互联网金融帐户存入
case 's':
if (ib_user.Deposit(money) == 0)
{
cout << "Bank balance not enough" << endl;
continue;
}
break;
case 'T': //从互联网金融转入银行帐户
case 't':
if (ib_user.Withdraw(money) == 0)
{
cout << "Internet bank balance not enough" << endl;
continue;
}
break;
case 'D': //直接向银行帐户存款
case 'd':
ib_user.BankCustomer::Deposit(money);
break;
case 'W': //直接从银行帐户取款
case 'w':
if (ib_user.BankCustomer::Withdraw(money) == 0)
{
cout << "Bank balance not enough" << endl;
continue;
}
break;
default:
cout << "Illegal input" << endl;
continue;
}
ib_user.setInterest(interest);
ib_user.calculateProfit();
//输出用户名,id
//输出银行余额
//输出互联网金融账户余额
ib_user.print();
}
}
return 0;
}
有点麻烦,耐心看看
题目四:进位与借位(虚函数和多态)
题目描述:
某小学二年级的数学老师在教学生整数加减法运算时发现:班上的同学可以分成三类,第一类可以正确地完成加减法运算(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为第三类学生)、第一个数、第二个数。
输出要求:
运算后的结果
输入样例:
3
1 79+81
2 81-79
3 183+69
输出样例:
160
12
142
代码示例:
#include
#include
#include
#include
#include
#include
using namespace std;
class Group
{
protected:
public:
virtual int add(int x, int y) = 0;//输出加法的运算结果
virtual int sub(int x, int y) = 0;//输出减法的运算结果
};
class GroupA :public Group
{
public:
virtual int add(int x, int y)
{
return x + y;
}
virtual int sub(int x, int y)
{
return x - y;
}
};
class GroupB :public Group
{
public:
virtual int add(int x, int y)
{
return x + y;
}
virtual int sub(int x, int y)
{
int xm[10], ym[10];
int i;
for (i = 0; x != 0 || y != 0; i++)
{
xm[i] = x % 10;
ym[i] = y % 10;
x /= 10;
y /= 10;
}
int sm[10];
for (int j = 0; j < i; j++)
{
if (xm[j] < ym[j])
{
sm[j] = xm[j] + 10 - ym[j];
}
else
{
sm[j] = xm[j] - ym[j];
}
}
int sum = 0;
for (int j = 0; j < i; j++)
{
sum += sm[j] * pow(10, j);
}
return sum;
}
};
class GroupC :public Group
{
public:
virtual int add(int x, int y)
{
int xm[10], ym[10];
int i;
for (i = 0; x != 0 || y != 0; i++)
{
xm[i] = x % 10;
ym[i] = y % 10;
x /= 10;
y /= 10;
}
int sm[10];
for (int j = 0; j < i; j++)
{
sm[j] = (xm[j] + ym[j]) % 10;
}
int sum = 0;
for (int j = 0; j < i; j++)
{
sum += sm[j] * pow(10, j);
}
return sum;
}
virtual int sub(int x, int y)
{
int xm[10], ym[10];
int i;
for (i = 0; x != 0 || y != 0; i++)
{
xm[i] = x % 10;
ym[i] = y % 10;
x /= 10;
y /= 10;
}
int sm[10];
for (int j = 0; j < i; j++)
{
if (xm[j] < ym[j])
{
sm[j] = xm[j] + 10 - ym[j];
}
else
{
sm[j] = xm[j] - ym[j];
}
}
int sum = 0;
for (int j = 0; j < i; j++)
{
sum += sm[j] * pow(10, j);
}
return sum;
}
};
int main()
{
int t;
cin >> t;
while (t--)
{
Group* g;
int n, x, y;
char c;
cin >> n >> x >> c >> y;
if (n == 1)
{
g = new GroupA;//无原始构造的基类指针指向对象
if (c == '+')
{
cout << g->add(x, y) << endl;
}
else if (c == '-')
{
cout << g->sub(x, y) << endl;
}
}
else if (n == 2)
{
g = new GroupB;
if (c == '+')
{
cout << g->add(x, y) << endl;
}
else if (c == '-')
{
cout << g->sub(x, y) << endl;
}
}
else if (n == 3)
{
g = new GroupC;
if (c == '+')
{
cout << g->add(x, y) << endl;
}
else if (c == '-')
{
cout << g->sub(x, y) << endl;
}
}
}
return 0;
}
注意题目要求的算法!
题目五:求最大面积(虚函数和多态)
题目描述:
请编写程序,从图形数组中找出最大面积。基类框架如下所示:
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是半径)。
输出要求:
最大图形的面积
输入样例:
3
1 3 4
2 5
2 6
输出样例:
最大面积=113.04
代码示例:
#include
#include
#include
#include
#include
#include
using namespace std;
class Geometry
{
public:
virtual double getArea() = 0; //计算面积,结果保留小数点后两位
};
class Rect :public Geometry
{
protected:
double x, y;
public:
Rect(double xx, double yy) :x(xx), y(yy) {}
virtual double getArea()
{
return x * y;
}
};
class Circle :public Geometry
{
protected:
double r;
public:
Circle(double rr) :r(rr) {}
virtual double getArea()
{
return 3.14 * r * r;
}
};
class TotalArea
{
public:
static void computerMaxArea(Geometry** t, int n)
{
double maxarea = 0;
for (int i = 0; i < n; i++)
{
if (t[i]->getArea() > maxarea)
{
maxarea = t[i]->getArea();
}
}
cout << "最大面积=" << fixed << setprecision(2) << maxarea << endl;
}
};
int main()
{
int t;
cin >> t;
Geometry** geo = new Geometry * [t];
for (int i = 0; i < t; i++)
{
int type;
cin >> type;
if (type == 1)
{
double x, y;
cin >> x >> y;
geo[i] = new Rect(x, y);
}
else if (type == 2)
{
double r;
cin >> r;
geo[i] = new Circle(r);
}
}
TotalArea total;
total.computerMaxArea(geo, t);//求最大面积
delete[]geo;
return 0;
}
注意二级指针的用法!