C++学习笔记——C++类层次结构要点

参考自《C++程序设计语言》、《Microsoft C++语言参考》

重载解析

重载解析的使用不会跨越不同类的作用域。来自不同基类的函数之间的歧义性不能基于参数类型完成解析。如果需要在不同的基类中使用同名函数,需要在使用前使用命名空间声明。(如果参数相同怎么办?

多继承

多重继承提供比单继承更好的灵活性,但是需要在引用部分成员是添加限定。多重继承主要要关注歧义性问题。因为C++查找成员的顺序是如果不能将名称解析为显示引用的类中的成员,编译器就会到该类的基类中找,此时会有三种结果,找到、找不到、有歧义。

虚继承

  • 可以实现菱形继承结构,即常规继承如果存在多继承,可能将一个类两次作为基类,存在多条继承路径。此时如果要引用基类的成员可能出现歧义性。派生类对象中可能存在多个基类的副本的情况。静态成员除外,类的静态成员只有一个副本
  • 虚继承中,通过虚继承派生的子类承诺共享虚基类的一份副本。此时再通过派生类派生的子类中访问虚基类就不会存在歧义性。
  • 另外,如果虚继承的情况中,只有某条路径覆盖了虚基类的成员,直接使用也不会引起歧义性,因为派生类中覆盖的成员有更高的优先级。但是如果在多于一条的虚继承路径中覆盖了虚基类的成员。那么还是会引起歧义性。

类的访问控制public、private、protected

  • 在对类成员使用关键字时:在class中,成员默认为private,struct中,成员默认为public
    • 一个成员是private,只能由所在类的成员函数和友元访问和使用。
    • 一个成员时protected,只能由所在类及其派生类的成员函数和友元访问和使用。
    • 一个成员是public,可以由任何函数访问和使用。
  • 在对继承使用关键字时(对基类使用关键字时)【对public成员的访问规则改变较大】
    • 基类是private,它的public和protected成员只能由派生类的成员函数和友元访问。只有D的成员和友元能将派生类指针转换到基类指针
    • 基类是protected,它的public和protected成员只能由派生类以及派生类的派生类的成员函数和友元访问。也只有他们能将派生类指针转换到基类指针
    • 基类是public,访问规则与成员访问控制规则一致。任何函数都能将派生类指针转换到基类指针。

类层次结构中漫游(强制类型转换)

1. dyanmic_cast

  • 要求多态性的操作对象。因为非多态性的操作对象不包含类型信息。

  • 能够保存一定的运行时需要的对象的类型信息,用于在类的继承和组合关系中进行安全的转换

  • 适用于基类与派生类之间的转换兄弟类之间的转换,以及能够由这两种场景复合构成的转换。(向上强制、向下强制、交叉强制)。

  • 由于实现的是安全的类型转换,所以通过if(C2* pc2 = dynamic_cast<C2*>(pc1)),判断指针在类型转换之后的返回值是否为0,来确定是否实现了安全的类型转换。对于引用的转换的合法性,则通过dynamic_cast本身检查。如果不能实现转换,则会抛出bad_cast,可以通过try...catch块设置处理器进行处理。

  • 另外由于编译器不能对void*所指向的存储提供任何保证,所以dynamic_cast不能实现从void*出发的强制转换,因为编译器需要去查看对象,确定类型。此时需要使用static_cast进行转换。

  • void*的synamic_cast可以用于确定多态类型的对象的起始地址。

  • 如果需要跨系统保存一个非多态类型的对象的类型信息,可以将非多态类型的对象包装在一个要穿过的系统的基类中。然后在需要使用的时候,利用dynamic_cast将对象提取出来。例如:

    class Io_obj{
    	virtual Io_obj* clone() = 0;
    };
    
    class Io_date : public Date, public Io_obj{};
    
    void f(Io_obj* pio){
    	Date* pd = dynamic_cast<Date*>(pio);
    }
    

2. static_cast

  • 对于dynamic_cast实现可用之前,有许多强制转换通过其他机制保证安全。所以dynamic_cast实现的一些操作包含冗余。同时dynamic_cast具有运行时开销。
  • 另外用于实现从void*出发的强制转换。

3. const_cast

  • 用于实现const指针与非const指针之间的转换。
  • 但是如果想要实现安全的转换,需要程序员保证该const指针(volatile)本来就不是使用const(或volatile)声明的。

4. reinterpret_cast

指向成员的指针

  • 与多态指针的差异

扩展的类结构信息——typeid

  • dynamic_cast保存更多类型信息
  • 满足如得到一个类的名字或者它的布局信息。

虚析构函数和自由存储

虚构造函数

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值