c++ 继承和多态

一、继承:是面向对象复用的重要手段。通过继承定义一个类,继承是类型之间的关系建模,共享共有的对象,实现各自本质不同的东西。

三种继承关系——public 共有继承 、  protected 保护继承 、  private 私有继承

              三种继承关系下基类成员在派生类的访问关系变化

继承方式基类的public成员基类的protected成员基类的private成员继承引起的访问控制关系变化
publicpublicprotected不可访问基类的非私有成员在子类的访问属性不变
protectedprotectedprotected不可访问基类的非私有成员都成为了子类的保护成员
privateprivateprivate不可访问基类的非私有成员都成为了子类的私有成员

总结:

1、基类的私有成员在子类中不能访问,如果有一些基类成员不想被基类对象直接访问,但需要在子类宏访问,就定义为protected。可以看出,protected是因为继承才出现的。

2、public继承是一个借口继承,保持is-a原则,每个父类可用的成员对子类也能 使用,因为每个子类对象也是一个父类对象。

3、protected/private 继承是一个实现继承,基类的部分成员并未完全成为子类接口的一部分,是has-a的关系原则。

4、不管哪种继承方式,在子类内部都可以访问基类的共有成员和保护成员,但是基类的私有成员存在但是在子类中不可见(不能访问)。

5、使用class时默认的继承方式是private,struct默认的继承方式是public,不过最好写出继承方式。在实际运用中大多数使用的都是public,极少场景才会使用protected/private。

复制兼容规则

1.子类对象可以复制给父类对象、指针、引用。

2、父类对象不能复制给子类对象。

3、父类指针、引用不能赋值给子类的指针/引用。但是可以强制类型转换。

继承体系中的作用域

1、基类和父类都有独立的作用域。

2、子类和父类中有同名成员,子类将屏蔽父类对成员直接访问。在子类的成员函数中可以使用 基类::基类成员 来访问。但是最好不要在子类和父类中用相同名定义成员。

单继承:一个类只有一个父类的继承关系

多继承:一个类有多个父类的继承

菱形继承:一个类的两个父类有同一个父类的菱形继承

问题1:一个不能被继承的类

把父类的构造函数设成私有的。

1、私有成员继承之后不可见;2、子类的构造函数是合成的

但是此时这个父类也无法生成对象,因为在类外面无法调用它的私有的构造函数。所以解决方法:

通过一个静态的返回一个对象;  通过返回匿名对象的拷贝构造来实现。

 

问题2:实现两个类。一个只能在堆上,一个只能在栈上

 

 

把构造设成私有,通过共有静态函数返回一个对象。防止随意实例化对象。注意:

此时可以通过使用这个创建好的a1来拷贝构造,此时新实例化的对象在栈上,所以,为了只能在堆上实例化出对象,要把类的构造、拷贝构造都设成私有。

 

二:虚函数&多态:

类的成员函数前面加virtual关键字,则这个成员函数称为虚函数。

虚函数的重写:当在子类的定义了一个和父类完全相同的虚函数时,则称子类的这个函数重写(覆盖)了父类的这个虚函数。

当使用基类的指针或引用调用重写的虚函数时,当指向父类调用的就是父类的虚函数,指向子类调用的就是子类的虚函数。

总结:

1、派生类重写基类的虚函数实现多态,要求函数名,参数列表,返回值完全相同。

2、基类中定义了虚函数,在派生类中该函数始终保持虚函数的特征。

3、只有类的成员函数才能定义为虚函数。

4、静态成员函数不能定义为虚函数,因为没有this指针。

5、如果要在类外定义虚函数,只能在声明时加virtual,定义时不能加virtual。

6、构造函数不能为虚函数。

7.不要在构造和析构中调用虚函数,在构造和析构中,对象是不完整的,容易出现未定义的错误。

8、最好把基类的析构函数声明为虚函数。

继承体系同名成员函数的关系:

重载:1、在同一作用域;2、函数名相同,参数列表不同;3、返回值也可以不同;

重写(覆盖):1、不在统一作用域;2、函数名,参数列表,返回值相同;3、父类函数必须用virtual关键字;4、访问修饰符可以不同;

重定义(隐藏):1、在不同作用域中;2、函数名相同;3、在基类和派生类中,只要不是重写,就是重定义;

纯虚函数:在成员函数的形参后面写上=0,则成员函数为纯虚函数。包含纯虚函数的类称为抽象类,也叫接口,抽象类不能实例化出对象。纯虚函数在子类中重定义以后,子类才能实例化出对象。

每个虚函数都存放在虚表中,类中有一个指向这个虚表的指针。

友元关系不能继承。

继承与静态成员:基类定义了一个static成员,则整个继承体系里只有一个这样的成员,无论派生出多少子类。

多态的实现——虚表

c++中虚函数的主要作用就是实现多态。每个对象都会有一个虚表。虚函数表是通过一块连续的内存来存储虚函数的地址。这张表解决了继承。虚函数(重写)的问题。

1、静态多态就是重载,因为是在编译器决议确定函数地址,称为静态多态。

2、动态多态就是通过继承重写基类的虚函数实现的多态,因为在运行时在虚表中找调用函数的地址,称为动态多态。

单继承的内存模式

菱形继承

用虚表也可观察菱形继承的内存管理形式。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值