SZTUC++实验课(多态)错误分析

多态错误总结

因为这次实验要求使用基类指针,将指针指向派生类对象。

因此有些问题具有共通点。

问题1

不能 “在条件语句中 创建对象 然后 在条件语句之后 使用它”

错误代码(D题为例)

Shape* s;
cin>>type>>name>>age;
if(type=="Tiger"){
    Tiger t(name,age);
    s=&t;//将s指针指向对象t
}
else if(type=="Pig"){
    Pig p(name,age);
    s=&p;
}
...
else{
    cout<<"There is no"<<type<<" in our zoo"<<endl;
}
s->speak();//调用基类指针指向对象的纯虚函数speack() 但是指向的对象均已销毁 

因为 在条件语句语句作用域中定义的变量,在跳出条件语句时,该变量将被释放(因此定义的条件语句内定义的派生类对象 在条件语句之后 被销毁了)

解决方法

1.在条件函数内调用各个派生类对象的speak()函数,看起来可能比较冗杂。

cin>>type>>name>>age;
if(type=="Tiger"){
    Tiger t(name,age);
    animal=&t;
    animal->speack();			
}else if(type=="Pig"){
    Pig p(name,age);
    animal=&p;
    animal->speack();	
}
...
}else{
    cout<<"There is no "<<type<<" in our Zoo."<<endl;
}

2.在条件语句中使用new运算符创建派生类对象,这样跳出条件语句后,new创建出来的内存空间不会被销毁,因为它是在堆上创建的,而不是栈。需要手动管理,注意使用delete,避免内存泄漏。

cin >> type >> name >> age;
if (type == "Tiger") p = new Tiger(name, age);
else if (type == "Pig") p = new Pig(name, age);
...
else {
cout << "There is no " << type << " in our Zoo." << endl;
}
p->speak();
delete p;
问题2

在switch语句内部定义变量,导致出错

错误代码(B题为例)

switch(type){
    case 1:
            cin>>num>>weight;
            Car car(no,num,weight);
            break;
    case 2:
            cin>>weight;
            Truck truck(no,weight);
            break;
	...		
}

报错信息:“jump to case label [-fpermissive]”,

因为C++语言规定:不允许跨过变量的初始化语句 直接跳转到 该变量作用域的另一个位置

当type=2时,此时控制流跳转到2分支,同时略过了car派生类对象初始化的过程,而switch语句中,所有的case语句都在同一作用域,这是不被允许的。

解决方法

1.直接不用switch

2.如果需要为某个case分支定义并初始化一个变量,我们应该把变量定义在块内,从而确保后面的所有case标签都在变量的作用域之外,这样就不会报错了。

switch(type){
    case 1:
        {
            cin>>num>>weight;
           	Car car(no,num,weight);
        }
            break;
    case 2:
        {
            cin>>weight;
            Truck truck(no,weight);
        }
            break;
	...		
}

A 图形面积(虚函数与多态)

将问题复杂化,导致加上析构就会错误(本身逻辑就有一些问题)

错误代码

int t;
double r,a,length,width;
cin >> t;
Shape** s = new Shape * [t];//定义一个 基类指针 数组,长度为t(已经出现问题)
for (int i = 0; i < t; i++)//t次循环 t个样例
{
    cin >> r >> a >> length >> width;
    s[0] = new Circle(r);//数组中 第一个基类指针
    s[1] = new Square(longth1);//数组中 第二个基类指针
    s[2] = new Rectangle(longth2, width2);//数组中 第三个基类指针
    for (int j = 0; j < 3; j++)
    {
        cout << fixed << setprecision(2) << s[j]->area() << endl;
    }
}
for (int i = 0; i < t; i++)//析构 s[0]~s[t-1] 实际上只有s[0]、s[1]、s[2]能够析构
{
    delete s[i];
}
delete[]s;

解决方法

已知每个样例 有3种派生类对象,分别是Circle、Square、Rectangle,这里可以直接定义一个具有3个基类指针元素的数组。直接将每一个元素指向每一个派生类对象

cin>>t;
while(t--){
    Shape* s[3];
    cin >> r >> a >> length >> width;
    s[0]=new Circle(r);
    s[1]=new Square(a);
    s[2]=new Rectangle(length, width);
    for(int i=0;i<3;i++){
        cout << fixed << setprecision(2) << s[i]->area() << endl;
        delete s[i];
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值