Problem F: 汽车、客车、货车
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 5956 Solved: 3503
[Submit][Status]
Description
定义Vehicle类,包括:
1. 一个int类型属性num,表示汽车的轮子数量。
2. 构造函数、析构函数,输出如样例所示的信息。
定义Bus类,是Vehicle类的子类,包括:
1. 一个int类型属性guest,表示客车可乘坐的人数。
2. 构造函数、析构函数,输出如样例所示的信息。
定义Truck类,是Vehicle类的子类,包括:
1. 一个int类型属性weight,表示货车可载荷的货物重量。
2. 构造函数、析构函数,输出如样例所示的信息。
Input
输入有多行,每行一个测试用例,每行包括1个正整数(车的轮子数量)、1个字符b或者t(b、t分别表示客车、货车)、1个正整数(可乘坐的人数或可承载的货物重量)。
Output
见样例。
Sample Input
4 b 40 8 t 15
Sample Output
Vehicle has 4 wheels is created. Bus which can carry 40 persons is created. Bus which can carry 40 persons is erased. Vehicle has 4 wheels is erased. Vehicle has 8 wheels is created. Truck which can carry 15 tons goods is created. Truck which can carry 15 tons goods is erased. Vehicle has 8 wheels is erased.
HINT
Append Code
int main()
{
int w, g;
char t;
Vehicle *veh;
while (cin>>w>>t>>g)
{
if (t == 'b')
{
veh = new Bus(w, g);
}
else
{
veh = new Truck(w, g);
}
delete veh;
}
return 0;
}
答案:
#include<iostream>
#include <string>
using namespace std;
class Vehicle
{
protected:
int n;
public:
Vehicle(int nn):n(nn)
{
cout<<"Vehicle has "<<n<<" wheels is created."<<endl;
}
virtual ~Vehicle()//虚析构,不然父类指针无法指向子类析构函数释放子类数据
{
cout<<"Vehicle has "<<n<<" wheels is erased."<<endl;
}
};
class Bus:public Vehicle
{
private:
int g;
public:
Bus(int ww,int gg):Vehicle(ww),g(gg)
{
cout<<"Bus which can carry "<<g<<" persons is created."<<endl;
}
~Bus()
{
cout<<"Bus which can carry "<<g<<" persons is erased."<<endl;
}
};
class Truck:public Vehicle
{
private:
int w;
public:
Truck(int nn,int ww):Vehicle(nn),w(ww)
{
cout<<"Truck which can carry "<<w<<" tons goods is created."<<endl;
}
~Truck()
{
cout<<"Truck which can carry "<<w<<" tons goods is erased."<<endl;
}
};
int main()
{
int w, g;
char t;
Vehicle *veh;
while (cin>>w>>t>>g)
{
if (t == 'b')
{
veh = new Bus(w, g);//父类指针指向子类对象
}
else
{
veh = new Truck(w, g);
}
delete veh;
}
return 0;
}
分析:
1.析构多态:
多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码
解决方式:将父类中的析构函数改为虚析构或者纯虚析构(当基类中的某函数被virtual修饰时(public),程序调用此函数,则会执行继承该基类的派生类中的方法。)
虚析构语法:
virtual ~类名(){}
纯虚析构语法:
virtual ~类名() = 0;
类名::~类名(){}
【语法强制纯虚析构函数必须有函数实现,因为有时父类也有一些数据开辟在堆区,既要使用纯虚函数,又要释放父类在堆区中的数据,就需要使用类内纯虚函数声明,类外写实现的写法。
注意:区别于纯虚函数可以只写声明不写实现,纯虚析构需要声明也需要实现。有了纯虚析构后,这个类也属于抽象类,无法实例化对象。】
2.如果不使用父类的指针或引用去调用虚函数,则只调用父类虚函数,若使用则调用子类
3.在重写基类虚函数时,派生类的虚函数不加virtual关键字也可以构成重写。
主要原因:因为继承后基类的虚函数被继承下来了,在派生类中依旧保持虚函数属性。
但是这种写法不是很规范,因为派生类也有可能会被继承,为了区分虚函数,建议在派生类的虚函数前也加上virtual关键字。