C++ Primer(面向对象编程 二)

来源:互联网 发布:识别颜色的软件 编辑:程序博客网 时间:2024/05/16 05:09

C++ Primer(面向对象编程 二)


15.5 继承情况下的类作用域

1.每个类都保持着自己的作用域,在该作用域中定义了成员的名字。在继承情况下,派生类的作用域嵌套在基类作用域中。如果不能在派生类作用域中确定名字,就在外围基类作用域中查找该名字的定义。

2.名字冲突与继承:与基类成员同名的派生类成员将屏蔽对基类成员的直接访问。使用作用域操作符访问被屏蔽成员。

struct Derived:Base{

int get_base_mem(){ return Base::mem; }

};

3.在派生类作用域中派生类成员将屏蔽基类成员。即使函数原型不同,基类成员也会被屏蔽。


4.重载函数:


a.像其他任意函数一样,成员函数(无论虚还是非虚)也可以重载。派生类可以重定义所继承的 0 个或多个版本。
b.为基类成员函数名称而作的 using 声明将该函数的所有重载实例加到派生类的作用域。


5.虚函数与作用域:要获得动态绑定,必须通过基类的引用或指针调用虚成员。虚函数必须在基类和派生类中拥有同一原型了。

6.通过基类调用被屏蔽的虚函数:通过基类类型的引用或指针调用函数时,编译器将在基类中查找该函数而忽略派生类

7.总结:名字查找与继承

理解 C++ 中继承层次的关键在于理解如何确定函数调用。确定函数调用遵循以下四个步骤:

a.首先确定进行函数调用的对象、引用或指针的静态类型。

b.在该类中查找函数,如果找不到,就在直接基类中查找,如此循着类的继承链往上找,直到找到该函数或者查找完最后一个类。如果不能在类或其相关基类中找到该名字,则调用是错误的。

c.一旦找到了该名字,就进行常规类型检查,查看如果给定找到的定义,该函数调用是否合法。

d.假定函数调用合法,编译器就生成代码。如果函数是虚函数且通过引用或指针调用,则编译器生成代码以确定根据对象的动态类型运行哪个函数版本,否则,编译器生成代码直接调用函数。



15.6 纯虚函数

类的头文件中在函数形参表末尾 =0 声明的虚函数。类不必(但可以)定义纯虚函数。带纯虚函数的类为抽象类。如果派生类没有定义所继承的纯虚函数的自身版本,则派生类也是抽象类。

在函数形参表后面写上 = 0 以指定纯虚函数:

class Disc_item : public Item_base {
public:
double net_price(std::size_t) const = 0;
};
1.将函数定义为纯虚能够说明,该函数为后代类型提供了可以覆盖的接口,但是这个类中的版本决不会调用。
2.试图创建抽象基类的对象将发生编译时错误
3.含有(或继承)一个或多个纯虚函数的类是抽象基类。除了作为抽象基类的派生类的对象的组成部分,不能创建抽象类型的对象。
15.7 容器与继承

我们希望使用容器(或内置数组)保存因继承而相关联的对象。但是,对象不是多态的,这一事实对将容器用于继承层次中的类型有影响。
1.如果定义 multiset 保存基类类型的对象:
multiset<Item_base> basket;
Item_base base;
Bulk_item bulk;
basket.insert(base); // ok: add copy of base to basket
basket.insert(bulk); // ok: but bulk sliced down to its base part
则加入派生类型的对象时,只将对象的基类部分保存在容器中。记住,将派生类对象复制到基类对象时,派生类对象将被切掉.
因为派生类对象在赋值给基类对象时会被“切掉”,所以容器与通过继承相关的类型不能很好地融合。

15.8 句柄类与继承

C++ 中一个通用的技术是定义包装(cover)类或句柄类。句柄类存储和管理基类指针。指针所指对象的类型可以变化,它既可以指向基类类型对象又可以指向派生类型对象。用户通过句柄类访问继承层次的操作。因为句柄类使用指针执行操作,虚成员的行为将在运行时根据句柄实际绑定的对象的类型而变化。因此,句柄的用户可以获得动态行为但无须操心指针的管理。









0 0
原创粉丝点击