C++ 多态(1)

1.多态的定义

定义:不同的人做同一事情会产生不同的形态(比如说,买车票,学生七五折,成人全票......)

就是在不同继承关系的类对象在调用同一函数时,产生不同的效果。

2.虚函数

2.1虚函数的定义

被virtual修饰的类成员函数叫做虚函数

复制代码
class Person
{	
public:
	virtual void BuyTicket() { cout << "买票-》全票" << endl; }
};

2.2虚函数的重写(重写是一种特殊的隐藏)

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

复制代码
class Person
{	
public:
	virtual void BuyTicket() { cout << "买票-》全票" << endl; }
};
class Student :public Person
{
public:
	//以前在继承中说到过隐藏的概念,但是在多态中叫重写
	virtual void BuyTicket() { cout << "买票-》半价" << endl; }
};

这就是一个标准的多态行为

2.2.1虚函数重写的特例---协变(基类与派生类的返回值类型不同)

基类虚函数返回基类对象的指针或者引用,派生类虚函数返回派生类对象的指针或者引用

复制代码
class A {};
class B :public A {};
class Person
{
public:
	virtual A* f() { return  new A; }
};
class Student :public Person
{
public:
	virtual B* f() { return new B; }
};

2.2.2析构函数的重写

规则:

  • 基类的析构函数必须加virtual(虚析构),才能让派生类的析构函数 "覆盖" 它。

  • 派生类的析构函数不用写virtual(但写了也没事),只要基类是虚析构,销毁时就会从子类到父类依次调用析构函数(先儿子后爸爸)。

  • 编译后析构函数的名称统一处理成destructor。

    class Person {
    public:
    virtual ~Person()
    {
    cout << "~Person" << endl;
    }
    };
    class Student:public Person
    {
    public:
    ~Student()
    {
    cout << "~Student" << endl;
    }
    };
    int main()
    {
    //用父类的指针指向子类
    Person* p1 = new Student;
    delete p1;//会先调用父亲的析构,在调用儿子的析构
    return 0;
    }

因此析构函数一定建议写成虚函数

2.3多态的条件(缺一不可)

  • 虚函数重写(虚函数是指被重写的函数是虚函数,要重写的函数不必是虚函数,但是建议都把virtual;其次,多态不一定非得是父类和子类,也可以是多个子类之间生成多态)
  • 父类指针或者引用调用虚函数

3.重载、覆盖**(重写)、隐藏(重定义)**的对比

多态调用,看指向者的类型,指向谁就调用谁的虚函数;

普通调用,看调用者的类型,调用调用者的函数;

4.c++11 override和final

  • final:修饰虚函数,表示改虚函数不能再被重写

    class Car
    {
    public:
    virtual void Drive()final{}
    };
    class Benz :public Car
    {
    public:
    //该Drive不能被重写
    virtual void Drive() { cout << 11 << endl; }
    };

同理,如果一个类不想被继承,那么在类名之后也加final

复制代码
class A final
{
};

或者可以将构造函数私有

复制代码
class A
{
private:
	A(){}//这样派生类就无法生成对象了
	//因为我们规定派生类的构造函数必须依靠基类的构造函数
};
  • override:检查派生类虚函数是否重写了基类某个虚函数,如果没有重写,编译报错

    class Car
    {
    public:
    virtual void Drive(){}
    };
    class Benz :public Car
    {
    public:
    //
    virtual void Drive() override { cout << "苏轼" << endl; }
    };

相关推荐
汉克老师25 分钟前
CSP-J 初赛(以满分为目标):第二十七课 《图的遍历——BFS广度优先搜索——像“水波纹”一样,一层一层地搜索》
c++·csp-j·小学生·学c++编程
晨欣26 分钟前
NVIDIA GPU 架构演进学习笔记(GPT-5.6 Terra 生成)
笔记·学习·gpu·显卡·nvidia·英伟达
闻缺陷则喜何志丹27 分钟前
【动态规划】P3609 [USACO17JAN] Hoof, Paper, Scissor G
c++·算法·动态规划·洛谷
小雪崩39 分钟前
嵌入式学习 day40:数据库
数据库·学习
汉克老师1 小时前
CSP-J 初赛(以满分为目标):第二十六课 《图的遍历——DFS深度优先搜索——从“树的先序遍历”走进真正的图世界》
c++·csp-j·小学生·学c++编程
程序猿编码1 小时前
基于GGML的C++17轻量化语音推理引擎:说话人识别与语音分析技术全解析
开发语言·c++·pytorch·深度学习·神经网络·大模型
一条破秋裤1 小时前
17_ADC原理与转换模式
笔记·stm32·学习
影视飓风TIM1 小时前
C++哈希表深度剖析:冲突处理、rehash、迭代器与unordered容器封装
c++·哈希算法·散列表
传奇开心果编程2 小时前
【Rust入门知识点学与练】第5课:函数
开发语言·学习·rust
C++ 老炮儿的技术栈2 小时前
Qt5 使用 QPainter 绘制阿基米德螺线
开发语言·c++·windows·qt·代码化