- 面向对象程序设计及C++实验指导(第3版)
- 朱立华 俞琼 郭剑主编
- 1053字
- 2022-04-18 11:03:29
第5章 继承性
1.例5-3的思考题:
如果将例5-3中的语句“Member mem;”从Derived类移至Base类中,运行结果会发生何种变化?
【分析与解答】创建obj时,系统将首先调用基类Base对象成员mem的构造函数,再调用Base的构造函数,最后调用Derived的构造函数。析构函数的执行次序与此相反。
修改后代码如下。
程序运行结果如下。
2.例5-4的思考题:
①如果将例5-4中Derived类的构造函数改为如下形式,是否可行?
②如果将Base类构造函数的声明改为如下形式,那么①中的改动是否可行?
③在Derived中共有两个x:一个是Derived继承自Base的x,另一个是对象成员d中的x,运行结果中的“x=100”输出的是哪一个x的值?
④在main()函数中能否使用obj.d.show()输出d中x的值?
【分析与解答】①C++规定基类的构造函数必须由派生类的构造函数来调用。如果初始化表中没有调用,系统将调用无参或默认参数的构造函数。本例中,Base类并没有提供这类构造函数,因此会发生语法错误,故不可行。
②从语法上看这样处理可以解决①的问题。但直接把Base(i)移入Derived的构造函数中,编译器会认为这里在重新定义一个形参i,它将其视作重复定义i,并给出一个语法错误。如果将这里的Base(i)改为Base(i+1)或者Base(6)可以消除语法错误。但对于程序设计者来说仍然达不到最初的目标。程序员的动机是给Derived类中继承自Base的成员x赋一个值。但实际上程序的执行效果是产生一个临时对象,并用i+1或者6赋值给临时对象的x,并且这一行执行完后临时对象马上就被析构。Derived类中的x仍是默认的值0。
如果将Base(i)改为“x=i”是否可行呢?仍然不可行,因为x是Base中的私有成员。如果x是一个公有或保护成员,那么这样处理从语法上来看是可行的,但不推荐这么做。
③show()中的语句“cout<<"x="<<x<<endl;”输出的是变量x,即继承自Base的x。
④不可以,因为d是Derived中的私有成员,外界无法访问。
3.例5-9的思考题:
如果将例5-9中Derived类构造函数的下述两条语句删除,并且Base1、Base2中只有一个类将Base声明为虚基类,那么程序的运行结果将如何变化?
【分析与解答】假设Base2将Base声明为虚基类,那么程序运行时,首先由Derived调用虚基类Base的构造函数,然后调用Base1基类Base的构造函数,再依次调用Base1和Base2的构造函数,最后调用Derived的构造函数。析构函数的调用次序与之相反。
假设Base1将Base声明为虚基类,那么程序运行时,首先由Derived调用虚基类Base的构造函数,然后调用Base1的构造函数,再调用Base2基类Base的构造函数,最后调用Base2和Derived的构造函数。析构函数的调用次序与之相反。
从上述讨论可以看出,两种情况下构造函数的执行次序并不一样,程序的运行结果也不相同。
(注:VS 2010下这样修改后有编译错误,应是VS 2010的bug)
①若Base2将Base声明为虚基类,则运行结果如下。
②若Base1将Base声明为虚基类,则运行结果如下。