C++ Primer(面向对象编程 二)
2015-01-13 20:55
190 查看
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)类或句柄类。句柄类存储和管理基类指针。指针所指对象的类型可以变化,它既可以指向基类类型对象又可以指向派生类型对象。用户通过句柄类访问继承层次的操作。因为句柄类使用指针执行操作,虚成员的行为将在运行时根据句柄实际绑定的对象的类型而变化。因此,句柄的用户可以获得动态行为但无须操心指针的管理。
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)类或句柄类。句柄类存储和管理基类指针。指针所指对象的类型可以变化,它既可以指向基类类型对象又可以指向派生类型对象。用户通过句柄类访问继承层次的操作。因为句柄类使用指针执行操作,虚成员的行为将在运行时根据句柄实际绑定的对象的类型而变化。因此,句柄的用户可以获得动态行为但无须操心指针的管理。
相关文章推荐
- C++ Primer 【第四版】第十五章 面向对象编程
- C++ Primer学习系列(5):复制控制/重载操作与转换/面向对象编程
- C++ Primer 学习笔记_72_面向对象编程 -句柄类与继承[续]
- C++ Primer 面向对象编程 15.2 基类和派生类 virtual
- C++ Primer学习-第15章 面向对象编程
- C++ Primer 学习笔记_73_面向对象编程 -再谈文本查询示范
- C++ primer第二次阅读学习笔记(第15章:面向对象编程)
- 【C++ Primer】第15章 面向对象编程
- C++ Primer 学习笔记_74_面向对象编程 -再谈文本查询示范[续/习题]
- 《C++ Primer》十五章面向对象编程例题1
- C++ Primer 学习笔记_71_面向对象编程 --句柄类与继承
- C++ Primer(第4版)-第4部分:面向对象编程与泛型编程——学习笔记
- C++ Primer 面向对象编程 15.3 基类派生类相互转换 15.4. 构造函数和复制控制
- 【C++ Primer】面向对象编程与泛型编程
- C++ Primer 面向对象编程 15.5 动态绑定和静态绑定 类作用域
- 再学C++ Primer(10)-面向对象编程
- C++ primer 面向对象编程
- 再学C++ Primer(10)-面向对象编程