第十五章:面向对象编程

1. 在C++中,通过基类的引用(或者指针)调用虚函数时,反生动态绑定.引用(或者指针)既可以指向基类对象,也可以指向派生类对象,这一事实是动态绑定的关键.用引用调用的虚函数在运行时确定,被调用的函数是引用(或者是指针)所指对象的实际类型所定义.(保留字只能在类的内部声明中,定义中不能有)

 2. 基类应该将派生类需要重定义的任意函数定义为虚函数

3. 可以认为protected访问标号是private和public的混合:

       ● 像private成员一样,protected成员不能被类的用户访问

       ● 像public成员一样,protected成员可被该类的派生类访问

       ● 派生类只能通过派生类对象访问其基类的protected成员,派生类对其基类类型对象的protected成员没有特殊的访问权限

4. 派生类中虚函数的声明必须与基类中的定义方式完全匹配,但也有一个例外:返回对基类类型的引用(或指针)的虚函数,派生类中的虚函数可以返回基类函数所返回类型的派生生类的引用(或指针).(按照我的理解这句话的意思说白了就是:当虚函数在基类中返回基类的引用(或指针),在派生类继承定义时,可以返回基类或者派生类对象的指针(或引用).而且,一旦函数在基类中声明为虚函数,他就一直为虚函数.派生类无法改变该函数为虚函数这一事实.派生类重载定义虚函数时,可以使用virtual保留字,但不是必须这样做.

 5. C++中的函数调用默认不使用动态绑定.满足动态绑定的两个条件:  只有指定为虚函数的成员函数才能进行动态绑定,成员函数默认为非虚函数,所以不进行动态绑定 必须通过基类类型的引用或者指针进行函数调用

6. 在某些情况下,希望覆盖虚函数机制并强制函数调用使用虚函数的特定版本.这时可以使用作用域操作符.并且只有成员函数中的代码才应该使用作用域操作符覆盖的虚函数机制

7. 像其他任何函数一样,虚函数也可以有默认实参.通常,如果有用在给定调用中的默认实参值,该值将在编译时确定.如果一个调用省略了具有默认值的实参,则所有的值由调用该函数的类型定义,与对象的动态类型无关.通过基类的引用或指针调用虚函数时,默认实参为在基类虚函数声明中指定的值,如果通过派生类的指针或者引用调用虚函数,则默认实参实在派生类的版本中声明的值. 这段话比较难理解,我的理解是: 程序输出:

8. 继承原则:

      ◆ 如果成员在基类中为private,则只有基类和基类的友元可以访问访问该成员.派生类不能访问基类的private成员,也不能使自己的用户能够访问哪些成员

      ◆ 如果是public或者protected,则派生类列表中使用的访问标号决定该成员在派生类中的访问级别: 

        如果是公有继承,基类成员保持自己的访问级别:基类的public成员为派生类的public,基类的protected成员为派生类的protected成员

        如果是受保护继承,基类的public和protected成员在派生类中为protected成员 如果是私有继承,基类的所有成员在派生类中为private成员

9. 继承与组合:前者反映”是一种(Is a)”的关系,后者是”有一个(has a)”的关系.

10. 使用class保留字定义的派生类默认具有private继承,而用struct保留字定义的类默认具有public继承

11. 友元关系不能继承.基类的友元对派生类的成员没有特殊的访问权限.如果基类被授予友元关系,则只有基类具有特殊访问权限,该基类的派生类不能访问授予友元关系的那个类.

 12. 如果基类定义了static成员,则整个继承层次中只有一个这样的成员.无论从基类派生出多少个派生类,每个static成员只有一个实例.如果成员在基类中为private,则派生类不能访问它.

13. 存在从派生类型引用到基类类型引用的自动转换,但是不存在反向转换. 将派生类对象传给希望接受引用的函数时,引用直接绑定到该对象,虽然看起来是在传递对象,但实际上实参是该对象的引用.对象本身并没有复制.并且转换不会在任何方面改变派生类型对象,该对象仍是派生类对象. 将派生类对象传递给接收基类类型对象的函数时,形参是固定的───在编译和运行时形参都是基类对象

14. 构造函数和赋值控制成员不能继承,每个类定义自己的构造函数和复制控制成员.

15. 构造函数初始化列表为类的基类和成员提供初始值,它并不指定初始化的执行顺序.首先初始化基类,然后根据声明次序初始化派生类成员 16. 如果派生类显示定义了自己复制构造函数或者赋值操作符,则该定义将完全覆盖默认定义,被继承类的复制构造函数和赋值操作符赋值对基类成员以及类自身的成员进行复制或者赋值.

17. 析构函数的工作与赋值构造函数和赋值操作符不同:编译器总是显示调用派生类对象基类部分的析构函数,因为其本身不会撤销基类的对象成员对象的撤销顺序与构造函数顺序相反:首先运行派生类析构函数,然后按继承层次依次向上调用各基类析构函数如果删除基类指针,则需要运行基类析构函数并清除基类的成员.如果对象实际上派生类型的,则没有定义该行为.要保证运行适当的析构函数,基类中的析构函数必须为虚函数,如果基类的析构函数为虚函数,则派生列析构函数也定为虚函数. 即使析构函数没有工作要做,继承层次的根类也应该定义一个虚析构函数另外,我们一般不要将赋值操作符设置为虚函数(主要是为了避免混淆).

18. 在析构和构造的时候,可能造成类型的不完整性,(主要是在构造和析构期间的对象类型对虚函数的绑定有影响. 如果在构造函数和析构函数中调用虚函数,则运行的是为构造函数或析构函数自身类型定义的版本.

19. 与基类成员同名的派生类成员将屏蔽对基类成员的直接访问.我们在设计派生类的时候,只要可能最好避免与基类成员的名称冲突.

 20. 在基类和派生类中使用同一名字的成员函数,其行为与数据成员一样:在派生类作用域中派生类成员将屏蔽基类成员.即使函数原型不同,基类成员也会被屏蔽.如果派生类不存在该函数时,就考虑基类函数.

21. 派生类不用重定义所继承的每一个基类版本,他可以为重载成员提供Using声明.一个Using声明只能指定一个名字,不能指定形参表,因此,为基类成员函数名称而做的Using声明将该函数所有重载实例加到派生类的作用域.将所有名字加入作用域后,派生类只需要重定义本类型确实必须定义的那些函数,对其他的版本可以使用继承定义的.

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

      ◆ 首先确定进行函数调用的对象,引用或者指针的静态类型.

      ◆ 在该类中查找函数,如果找不到,就在基类中查找.如此循着累的集成链往上找.

      ◆ 找到了改名字,就立即进行类型检查.

      ◆ 假定调用合法,编译器便生成代码

23. 含有(或继承)一个或多个纯虚函数的类是抽象类.除了作为抽象基类的派生类的对象的组成部分,不能创建抽象类型的对象.

24. 因为派生类对象在赋值给基类对象时会被”切掉”,所以容器与通过继承相关联的类型不能很好的融合.

25. 句柄类:提供到其他类的接口的类,句柄类存储和管理基类指针. 包装了继承层次的句柄有两个重要的设计考虑因素:

      ● 像对任何保存指针的类一样,必须确定对赋值控制做些什么.包装了继承层次的句柄通常表现的像一个只能指针或者像一个

      ● 句柄类决定句柄接口屏蔽还是不屏蔽继承层次,如果不屏蔽继承层次,用户必须了解和使用基本层次中的对象

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值