类继承

本文深入探讨C++中类的继承机制,包括虚函数的作用、构造与析构函数的调用顺序、派生类与基类之间的交互细节等。同时解答了关于赋值运算符、对象传递方式及效率对比等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

知识点

有如下程序

class Brass

{

private:

...

public:

...

virtual void ViewAcct() const

virtual ~Brass() {}

};

 

class Brass : public Brass

{

private:

...

public:

virtual void ViewAcct() const;

...

}

(1)如果通过对对象调用,程序将使用对象类型来确定哪个

Brass dom (...);

BrassPlus dot (...)

dom.ViewAcct(); // use Brass::ViewAcct

dot.ViewAcct(); // use BrassPlus::ViewAcct

(2)如果方法是通过引用或指针而不是对象调用

A. 如果没有使用virtual关键字,程序将根据引用类型或指针类型选择方法

Brass dom (...);

BrassPlus dot (...);

Brass & b1_ref = dom;

Brass & b2_ref = dot;

b1_ref.ViewAcct(); // use Brass::ViewAcct()

b2_ref.ViewAcct(); // use Brass::ViewAcct()

解释:引用变量的类型是Brass,所以选择了Brass::ViewAcct()。

B. 如果使用了virtual关键字,程序根据引用或指针指向的对象的类型来选择方法

Brass dom (...);

BrassPlus dot (...);

Brass & b1_ref = dom;

Brass & b2_ref = dot;

b1_ref.ViewAcct(); // use Brass::ViewAcct()

b2_ref.ViewAcct(); // use BrassPlus::ViewAcct()

解释:两个引用类型都是Brass,但b2_ref引用的是一个BrassPlus对象,所以使用use BrassPlus::ViewAcct()

 

相关问题

1 派生类从基类那里继承了什么,不能从基类那里继承什么?

答:派生类继承基类的数据成员和大部分方法,不能继承基类的构造函数、析构函数、赋值运算符、友元函数。

 

2 假设baseDMA::operator=()函数的返回类型为void,而不是baseDMA &,这将造成什么后果?如果返回类型为baseDMA,而不是baseDMA &,又将是什么后果?

答:返回的是void,可以进行单个赋值,但是不能进行连续赋值 ,例如a=b=c的情况;

返回的是baseDMA,可返回一个副本,增加程序时间和内存的消耗,效率降低。

 

3 创建和删除派生类对象时,构造函数和析构函数的调用顺序是怎样的?

答:创建派生类对象时,将首先调用基类的构造函数,然后调用派生类的构造函数;删除派生类对象时,将首先调用派生类的析构函数,然后调用基类的析构函数。

 

4 如果派生类没有添加任何数据成员,它是否需要构造函数?

答:需要。派生类不能继承基类的构造函数,即使自己不写,系统也会默认生成一个。

 

5 如果基类和派生类定义了同名的方法,当派生类对象调用该方法时,被调用的将是哪个方法?

答:只调用派生类方法。因为派生类定义的方法取代基类定义的方法;派生类的重新定义的方法应该声明为虚函数。

仅当派生类没有重新定义方法或者使用作用域解析操作符时,才会调用基类方法。

 

6 在什么情况下,派生类应定义赋值运算符?

答:在派生类构造函数中使用new或new[]来初始化指针成员的时候。

若在派生类构造函数中使用new或new[]来初始化指针成员,派生类还应该定义复制构造函数、显示析构函数

 

7 可以将派生类对象的地址赋给基类指针吗?可以将基类对象的指针赋给派生类指针吗?

答:可以将派生类对象的地址赋给基类指针。使用显示类型转换,也可以将基类对象的指针赋给派生类指针。

 

8 可以将派生类对象赋给基类对象吗?可以将基类对象赋给派生类对象吗?

答:可以将派生类对象赋给基类对象。派生类中新增的数据成员都不会传给基类对象。

仅当派生类定义了转换操作(即包含将基类引用作为唯一参数的构造函数)或使用基类为参数的赋值操作符,基类对象赋给派生类对象。

 

9 假设定义了一个函数,它将基类对象的引用作为参数。为什么该函数也可以将派生类对象作为参数?

答:因为C++允许基类引用指向该基类派生而来的任何类型。

 

10 假设定义了一个函数,它将基类对象作为参数(即函数按值传递基类对象)。为什么该函数也可以将派生类对象作为参数?

答:按值传递将调用复制构造函数。由于形参是基类对象,因此调用基类的复制构造函数。复制构造函数以基类引用为参数,该引用可以指向作为参数传递的派生类对象。最终结果是将生成一个基类的临时对象,其成员对应于派生类对象的基类部分

 

11 为什么通常按引用传递对象比按值传递对象的效率高?

答:按值传递是建立一个临时对象,然后将参数的值复制到这个新的对象中。而引用传递则直接使用原来的对象,省去了很多的功夫。

另外如果函数内使用了对象的某个虚函数,则会优先调用派生类的函数

 

12 假设Corporation是基类,PublicCorporation是派生类。再假设这两个类都定义了head()函数,ph是指向Corporation类型的指针,且被赋给了一个PublicCorporation对象的地址。如果基类将head()函数定义为:

A. 常规非虚方法;

B. 虚方法

ph ->head()将被如何解释?

答:A 调用基类函数 ph->head()将调用Corporation::head()

 B 调用派生类函数 ph->head()将调用PublicCorporation::head()

 

13 下属代码有什么问题

class Kitchen

{

Private:

Double kit_sq_ft;

Public:

Kitchen() {kit_sq_ft = 0.0;}

Virtual double area() const {return kit_sq_ft;}

};

 

Class House:public Kitchen

{

Private:

Double all_sq_ft;

Public:

House() {all_sq_ft += kit_sq_ft;}

Double area(const char *s) const {cout << s; return all_sq_ft;}

};

1)首先从语义上来看,厨房和房子不是is-a关系,而是has-a关系,所以不应该使用继承,而是将Kitchen作为House的一个成员。

2)kit_sq_ft是私有成员,House中无法直接访问。

3)除了声明为成员,还可以构造一个虚基类,因为们都有长度,面积之类的属性。

4)House的area()函数,隐藏了基类的。因为们特征标不同。

 

参考

C++ Primer Plus(第六版)》(26)(第十三章 类继承 复习题答案)

http://blog.youkuaiyun.com/u012175089/article/details/53898671

类继承复习题

http://blog.youkuaiyun.com/u013271921/article/details/44676979

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值