Bug现形记(一):一个多重继承程序的查错

简介:   【课程支撑】我的 C++程序设计课程教学材料  要完成的任务详见第12周-任务2-双肩挑干部。题目要求  分别定义Teacher(教师)类和Cadre(干部)类,采用多重继承方式由这两个类派生出新类Teacher_Cadre(教师兼干部)。要求:  (1)在两个基类中都包含姓名、年龄、性别、地址、电话等数据成员。  (2)在Teacher类中还包含数据成员title(职称),在Cadr

  【课程支撑】我的 C++程序设计课程教学材料

  要完成的任务详见第12周-任务2-双肩挑干部。题目要求

  分别定义Teacher(教师)类和Cadre(干部)类,采用多重继承方式由这两个类派生出新类Teacher_Cadre(教师兼干部)。要求:
  (1)在两个基类中都包含姓名、年龄、性别、地址、电话等数据成员。
  (2)在Teacher类中还包含数据成员title(职称),在Cadre类中还包含数据成员post(职务),在Teacher_Cadre类中还包含数据成员wages(工资)。
  (3)对两个基类中的姓名、年龄、性别、地址、电话等数据成员用相同的名字,在引用这些数据成员时,指定作用域。
  (4)在类体中声明成员函数,在类外定义成员函数。
  (5)在派生类Teacher_Cadre的成员函数show中调用Teacher类中的display函数,输出姓名、年龄、性别、职称、地址、电话,然后再用cout语句输出职务与工资。

  下面是某同学的解答:

#include <iostream>   
#include <string>

using namespace std;  
class Teacher
{
public:
	Teacher(string nam, int a, char s, string addr, string tel,string t);
	void display();
protected:
	string name;
	int age;
	string title;
	string address;
	char sex;
	string telep;
};

class Cadre
{
public:
	Cadre(string nam, int a, char s, string addr, string t,string p);
	void display1();
protected:
	string name;
	int age;
	string address;
	char sex;
	string telep;
	string post;
};
class Teacher_Cadre:public Teacher,public Cadre
{
public:
	Teacher_Cadre(string nam, int a, char s, string addr, string tel,float w,string t,string p);
	void show();
protected:
	string name;
	int age;
	string title;
	string address;
	char sex;
	string telep;
	string post;
	float wages;
};

void Teacher::display()
{
	cout<<Teacher::name<<" "<<Teacher::age<<" "<<Teacher::sex<<" "<<Teacher::address<<" "<<Teacher::telep<<" "<<title<<endl;
}

void Cadre::display1()
{
	cout<<post<<endl;
}
void Teacher_Cadre::show()
{
	display();
	cout<<wages<<endl;
}

Teacher::Teacher(string nam, int a, char s, string addr, string tel,string t)
{
	name=nam;
	age=a;
	address=addr;
	telep=tel;
	title=t;
}
Cadre::Cadre(string nam, int a, char s, string addr, string tel,string p)
{
	name=nam;
	sex=s;
	age=a;
	address=addr;
	telep=tel;
	post=p;
};
Teacher_Cadre::Teacher_Cadre(string nam, int a, char s, string addr, string tel,float w,string t,string p):Teacher(nam,a,s,addr,tel,t),Cadre(nam,a,s,addr,tel,p)
{
	wages=w;
}

void main()
{	
	Teacher_Cadre t1("malin",19,'f',"yantai","18253593419",10000,"student","study");
	t1.show();
	t1.display1();
	system("Pause");
}

程序的运行结果是:

  注意到画红圈的地方。寻找程序执行的流程,应该执行的是第50行,是Teacher::display()输出对象t1信息时显示了这一行。很时显,红圈中的?应该是性别 f 。看第50行没有问题,那究竟在哪儿见着鬼了?

  我决定用我们的法宝,调试工具这个照妖镜试试。问题出现在显示时,我在第88行t1.show();处加了断点并运行程序,打开自动窗口(窗口中出现的正是当前代码行涉及的对象的当前值),真相马上出现了。先看截屏:


  可以看到,可疑之处要输出的性别sex出现了3次:①来自基类Teacher;②来自基类Cadre;③来自派生类Teacher_Cadre。根据第50行代码可以判断,运行时出现的异常由于Teacher::sex造成的,而①处取值恰好为 ‘?’(其ASCII码值为52)。症状掌握了。那病因何在呢?

  显然,问题不在88行的show()函数,也不是48行Teacher::display()的毛病。问题出现在显示之前,对象根本没有获得正确的sex值。87行在定义对象时做了初始化,这个程序很短,疑点马上集中在对t1的初始化上。按照构造函数的执行过程逆着推上去,罪犯显形了:在63-70行Teacher的构造函数Teacher::Teacher(...)中,唯独缺少了对sex 数据成员的赋值!

  罪状昭然于天下,Bug伏法吧!

  单就运行结果看,程序没有问题了。但高度的责任感让我想到③处还有个问号。再一看,来自派生类Teacher_Cadre中的数据成员,除了wages的值正确,其他全……。推及Teacher_Cadre的构造函数(80-83行),确实,只给wages做了初始化。

  如果简单些处理,在Teacher_Cadre::Teacher_Cadre(...)中再加些赋值不就行了?事情没有这么简单。看Teacher_Cadre的声明(32-46行),其数据成员多达8个!Teacher_Cadre继承了两个类的数据成员,其中有同名的造成了二义性,这还不够麻烦,又将那些数据成员照抄着来了一份,这样,在派生类的对象中,同名的数据成员将被存储3份。如果这样的话,继承还有何用?这反映了对继承的理解还没有到位,或许仅是粗心了。

  如何更改程序,读者应该清楚了。

  作为结尾,再次提醒同学们用好调试工具。


  【课程支撑】我的 C++程序设计课程教学材料


目录
相关文章
|
6月前
|
存储 Cloud Native 编译器
C++编译期多态与运行期多态
C++编译期多态与运行期多态
|
9月前
面试题:多态是编译时行为还是运行时行为?
面试题:多态是编译时行为还是运行时行为?
39 0
|
6月前
|
编译器 C++
《C++避坑神器·六》多继承下问题处理(同名变量,信号槽,多态内存释放)
《C++避坑神器·六》多继承下问题处理(同名变量,信号槽,多态内存释放)
27 0
|
12月前
|
安全 Java 编译器
3 亿美元的 bug,Kotlin 帮你避免 | 内联类 value class
3 亿美元的 bug,Kotlin 帮你避免 | 内联类 value class
92 0
|
Java C++
多重继承有时候确实有必要
多重继承有时候确实有必要
35 0
|
Java
Java面向对象进阶4——多态的弊端及解决方法
多态本身是子类类型向父类类型向上转换(自动转换)的过程,这个过程是默认的。当父类引用指向一个子类对象时,便是向上转型。
88 0
Java面向对象进阶4——多态的弊端及解决方法
|
编译器 C++
Win32汇编:仿写多态与虚函数
多态性是面向对象的重要组成部分,利用多态可以设计和实现易于扩展的程序,所谓多态就是一个类函数有多重形态,具有不同功能的函数可以用同一个函数名,实现使用一个函数名调用不同内容的函数,从而返回不同的结果,这就是多态性,多态离不开虚函数的支撑,以下案例本人将深度分析虚函数实现机制,并通过汇编实现虚函数机制。
171 0
|
Java Maven
你有没有掉进去过这些 抽象类 和 接口 的 “陷阱“
你有没有掉进去过这些 抽象类 和 接口 的 “陷阱“
你有没有掉进去过这些 抽象类 和 接口 的 “陷阱“
|
存储 安全 Java
Kotlin刨根问底(三):你真的懂泛型,会用吗?(上)
本文灵感来源:群友提出泛型相关的问题,感觉很多人对泛型并不是很了解~ Kotlin中的泛型和Java中的泛型其实大同小异,只是语法稍微有些不同。 大部分内容摘取自:《Kotlin实用指南》
148 0
DHL
|
算法 Java 编译器
容易被忽视的几个 Kotlin 细节, value class 执行效率竟然这么高
今天这篇文章主要介绍 value class 和 data class 的区别,这可能是平时在做业务开发的时候,容易被忽视的几个细节。通过这篇文章,你将学习到以下内容。
DHL
384 0
容易被忽视的几个 Kotlin 细节, value class 执行效率竟然这么高