浅谈C++中继承与多态的区别

众所周知,C++有三大特性和五大原则,这三大特性分别是:封装、继承和多态。然而继承和多态这两个特性是许多人容易混淆的。

今天我们就来聊聊C++中继承和多态的区别。

看文章之前,别忘了关注我们,在我们这里,有你所需要的干货哦!


1.基础概念

(1)继承

指可以让某个类型的对象,获得另一种类型对象属性的方法。实际上就是类与类之间可以共用代码,实现代码重用。

继承支持按级分类的概念。它可以使用现有类的所有功能,并在无需重新编写原来类的情况下对这些功能进行扩展。

继承的过程:从一般到特殊的过程。

实现继承的方式:可以通过 “继承”(Inheritance)和“组合”(Composition)来实现。

与继承相关的类类型:

​ **基类:**被继承的类,即"父类"或“超类”。

​ **派生类:**基于基类创建的新类,又称“子类”。派生类可以访问基类中所有的非私有成员。

//派生类创建格式:
	class derived-class : access-specifier base-class
	/*
		①access-specifier表示继承类型。我们几乎不使用 protected 或 private 继承,通常使用 public 			继承。若如果未使用访问修饰符 access-specifier,则默认为private。
		②base-class表示已有基类
	*/

代码实现:

// 基类
 class Animal {
   // eat() 函数
   // sleep() 函数
 };

//派生类
 class Dog : public Animal {
   // bark() 函数
 };

***继承几种类型:***继承类型是通过上面讲解的访问修饰符 access-specifier 来指定的。

private:私有继承

​ 基类private成员 不能继承 ​ 基类public、protected成员,可以继承,在派生类中需要通过private访问

protected:保护继承:

​ 基类private成员 不能继承 ​ 基类public成员,可以继承,在派生类中相当于是protected访问 ​ 基类protected成员,可以继承,在派生类中相当于是protected访问

public:公有继承:

​ 基类private成员 不能继承 ​ 基类public成员,可以继承,在派生类中相当于是public访问 ​ 基类protected成员,可以继承,在派生类中相当于是protected访问

派生方式
基类的public成员
基类的protected成员
基类的private成员
派生方式引起的访问属性变化概括

private派生

变为private成员

变为private成员

不可见

基类的非私有成员都成为派生类的私有成员

protected派生

变为protected成员

变为private成员

不可见

基类的非私有成员在派生类中的访问属性都降一级

public派生

仍为public成员

仍为protected成员

不可见

基类的非私有成员在派生类中的访问属性保持不变

(2)多态

按字面的意思就是多种形态,指一个类实例的相同方法在不同情况下有不同表现形式。

多态机制使内部结构不同的对象可以共享相同的外部接口。即子类可以重写父类的某个函数,从而为这个函数提供不同于父类的行为。一个父类的多个子类可以为同一个函数提供不同的实现,从而在父类这个公共的接口下,表现出多种行为。

多态的使用场景:当类之间存在层次结构,并且类之间是通过继承关联时。这意味着,虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。

在C++中,多态性的实现和联编(也称绑定)这一概念有关。主要分为静态联编动态联编两种

  • 静态联编支持的多态性 称为编译时多态性(静态多态性)。在C++中,编译时多态性是通过函数重载和模板实现的。利用函数重载机制,在调用同名函数时,编译系统会根据实参的具体情况确定索要调用的是哪个函数。

  • 动态联编所支持的多态性 称为运行时多态(动态多态)。在C++中,运行时多态性是通过虚函数来实现的。

再举一个通俗易懂的例子:比如购买车票,普通人是全价票;学生是半价票等。

多态实现的三个条件:

​ ①必须是公有继承 ​ ②必须是通过基类的指针或引用 指向派生类对象 访问派生类方法 ​ ③基类的方法必须是虚函数,且完成了虚函数的重写

例如:

//tips:虚函数指在类的成员函数前加**virtual**关键字。
#include <iostream> 
using namespace std;

// 基类
class Shape {
   protected:
      int width, height;
   public:
      Shape( int a=0, int b=0)
      {
         width = a;
         height = b;
      }
      virtual int area()
      {
         cout << "Parent class area :" <<endl;
         return 0;
      }
};

// 派生类
class Rectangle: public Shape{
   public:
      Rectangle( int a=0, int b=0):Shape(a, b) { }
      int area ()
      { 
         cout << "Rectangle class area :" <<endl;
         return (width * height); 
      }
};

// 程序的主函数
int main( )
{
   Shape *shape;
   Rectangle rec(10,7);
 
   // 存储矩形的地址
   shape = &rec;
   // 调用矩形的求面积函数 area
   shape->area();
   
   return 0;
}

运行结果:Rectangle class area

(Tips: shape中的area函数若没有用virtual定义,则无法实现调用派生类中area函数的目的)

2.继承和多态的区别

区别:

1.多态的实现要求必须是共有继承。

2.继承关系中,并不要求基类方法一定是虚函数。而多态时,要求基类方法必须是虚函数。

3.多态:子类重写父类的方法,使得子类具有不同的实现。且运行时,根据实际创建的对象动态决定使用哪个方法。

总结

​ 在面向对象过程中,通常我们会以多个对象共有的特性作为基类进行创建。然后利用继承的特性,对基类进行派生。

​ 基类与派生类存在相同的方法,但是有不同的方法体。当调用这些方法体时就需要利用C++的多态性质,根据对象的特性有选择的对方法进行调用。即多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。

其它干货

引用

  • https://blog.csdn.net/qq_37185716/article/details/75044620

  • https://www.runoob.com/cplusplus/cpp-inheritance.html

  • https://www.runoob.com/cplusplus/cpp-polymorphism.html

Last updated