【C++进阶学习】C++中的多态(1)

简介: 【C++进阶学习】C++中的多态(1)

零、前言


C++有五大特性:对象,封装,继承,抽象和多态。而本章则将学习讲解C++中的多态


一、多态的概念和定义


概念:

通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态


示例:买票

普通人买票时,是全价买票;学生买票时,是半价买票;军人买票时是优先买票


定义:

多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为


多态构成条件:


必须通过基类的指针或者引用调用虚函数


被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写


示图:


image.png



二、虚函数


1、概念和定义


  • 虚函数语法:


被virtual修饰的类成员函数称为虚函数


  • 示例:


class Person {
public:
  virtual void BuyTicket() 
  { 
    cout << "买票-全价" << endl; 
  }
};



  • 虚函数重写:


派生类中有一个跟基类完全相同的虚函数(即派生类虚函数与基类虚函数的返回值类型、函数名字、参数列表完全相同),称子类的虚函数重写了基类的虚函数


  • 示例:


class Person {
public:
  virtual void BuyTicket() 
  { 
    cout << "买票-全价" << endl; 
  }
};
class Student : public Person {
public:
  virtual void BuyTicket()
  { 
    cout << "买票-半价" << endl;
  }
};
void Func(Person& p)
{
  p.BuyTicket();
}
int main()
{
  Person ps;
  Student st;
  Func(ps);
  Func(st);
  return 0;
}


2、虚函数重写的特例


  1. 协变


类虚函数返回基类对象的指针或者引用,派生类虚函数返回派生类对象的指针或者引用时,称为协变(基类与派生类虚函数返回值类型不同)


  • 示例:


class A {};
class B : public A {};
class Person {
public:
  virtual A* f() 
  { 
    cout << "virtual A* f()" << endl;
    return new A; 
  }
};
class Student : public Person {
public:
  virtual B* f() 
  { 
    cout << "virtual B* f()" << endl;
    return new B; 
  }
};
void Func(Person& p)
{
  p.f();
}
int main()
{
  Person ps;
  Student st;
  Func(ps);
  Func(st);
  return 0;
}


  1. 派生类虚函数不加virtual


在重写基类虚函数时,派生类的虚函数在不加virtual关键字也可以构成重写


  • 原因:


继承后基类的虚函数被继承下来了在派生类依旧保持虚函数属性)


  • 示例:


class Person {
public:
  virtual void BuyTicket()
  {
    cout << "买票-全价" << endl;
  }
};
class Student : public Person {
public:
  //派生类虚函数不加virtual也构成虚函数
  void BuyTicket() 
  { 
    cout << "买票-半价" << endl; 
  }
};
void Func(Person& p)
{
  p.BuyTicket();
}
int main()
{
  Person ps;
  Student st;
  Func(ps);
  Func(st);
  return 0;
}


注意:

该种写法不是很规范,不建议这样使用


如果基类的虚函数不加virtual,派生类的虚函数加virtual,这种情况是不构成虚函数的


析构函数的重写

我们知道,基类指针和引用可以指向基类和派生对象,由此通过指针和引用释放对象时需要实现析构的多态,但基类与派生类析构函数名字不同


为了解决,编译器对析构函数的名称做了特殊处理,编译后析构函数的名称统一处理成destructor


示例:


class Person {
public:
  virtual ~Person() 
  { 
    cout << "~Person()" << endl; 
  }
};
class Student : public Person {
public:
  virtual ~Student() 
  { 
    cout << "~Student()" << endl; 
  }
};
//只有派生类Student的析构函数重写了Person的析构函数
//当delete对象调用析构函数,才能构成多态,才能保证p1和p2指向的对象正确的调用析构函数
int main()
{
  Person* p1 = new Person;
  Person* p2 = new Student;
  delete p1;
  delete p2;
  return 0;
}
相关文章
|
4天前
|
C++
【C++】从零开始认识多态(二)
面向对象技术(oop)的核心思想就是封装,继承和多态。通过之前的学习,我们了解了什么是封装,什么是继承。 封装就是对将一些属性装载到一个类对象中,不受外界的影响,比如:洗衣机就是对洗衣服功能,甩干功能,漂洗功能等的封装,其功能不会受到外界的微波炉影响。 继承就是可以将类对象进行继承,派生类会继承基类的功能与属性,类似父与子的关系。比如水果和苹果,苹果就有水果的特性。
24 1
|
4天前
|
C++
【C++】从零开始认识多态(一)
面向对象技术(oop)的核心思想就是封装,继承和多态。通过之前的学习,我们了解了什么是封装,什么是继承。 封装就是对将一些属性装载到一个类对象中,不受外界的影响,比如:洗衣机就是对洗衣服功能,甩干功能,漂洗功能等的封装,其功能不会受到外界的微波炉影响。 继承就是可以将类对象进行继承,派生类会继承基类的功能与属性,类似父与子的关系。比如水果和苹果,苹果就有水果的特性。
26 4
|
4天前
|
C++ 编译器 存储
|
4天前
|
存储 C++
C++中的多态
C++中的多态
8 0
|
4天前
|
编译器 C++
【C++】继续学习 string类 吧
首先不得不说的是由于历史原因,string的接口多达130多个,简直冗杂… 所以学习过程中,我们只需要选取常用的,好用的来进行使用即可(有种垃圾堆里翻美食的感觉)
9 1
|
4天前
|
算法 安全 程序员
【C++】STL学习之旅——初识STL,认识string类
现在我正式开始学习STL,这让我期待好久了,一想到不用手撕链表,手搓堆栈,心里非常爽
16 0
|
4天前
|
存储 安全 测试技术
【C++】string学习 — 手搓string类项目
C++ 的 string 类是 C++ 标准库中提供的一个用于处理字符串的类。它在 C++ 的历史中扮演了重要的角色,为字符串处理提供了更加方便、高效的方法。
18 0
【C++】string学习 — 手搓string类项目
|
4天前
|
存储 编译器 C++
[C++基础]-多态
[C++基础]-多态
|
4天前
|
编译器 C语言 C++
【C++入门学习指南】:函数重载提升代码清晰度与灵活性
【C++入门学习指南】:函数重载提升代码清晰度与灵活性
23 0
|
4天前
|
设计模式 安全 算法
【C++入门到精通】特殊类的设计 | 单例模式 [ C++入门 ]
【C++入门到精通】特殊类的设计 | 单例模式 [ C++入门 ]
18 0