C++中多态的使用和建立条件

编程入门 行业动态 更新时间:2024-10-08 18:40:50

C++中多态的使用和建立<a href=https://www.elefans.com/category/jswz/34/1771358.html style=条件"/>

C++中多态的使用和建立条件

一、多态引入

多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。
C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。

根据代码,引入多态的概念:

#include <iostream>
using namespace std;//定义一个成人类
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);  // void Func(Person& p) 参数传参,函数调用Func(st);  // void Func(Person& p) 参数传参,函数调用return 0;
}


执行结果可以看出根据对象的不同,调用出来不同的结果

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

修改上面的代码,观察结果:
#include <iostream>
using namespace std;class Person {
public://修改前:virtual void BuyTicket() { cout << "成人买票-全价" << endl; }void BuyTicket() { cout << "成人买票-全价" << endl; }
};class Student : public Person {
public://修改前:virtual void BuyTicket() { cout << "学生买票-半价" << endl; }void BuyTicket() { cout << "学生买票-半价" << endl; }
};void Func(Person& p)
{p.BuyTicket();
}
int main()
{Person ps;Student st;Func(ps);Func(st);return 0;
}


我们去掉virtual 关键字之后,看到结果都是调用父类的BuyTicket()函数。 原因分析:student类继承person类,两个类里面的BuyTicket()函数函数名一样,构成重定义(1.函数名相同 2.两个函数分别在父子类的作用域里 3. 父子类的同名函数不构成重写),所以子类对象赋值给父类对象的时候,会将子类对象中的父类切出来,自然而然调用的是父类的成员函数

我们再修改代码,思考结果:
#include <iostream>
using namespace std;class Person {
public:virtual void BuyTicket() { cout << "成人买票-全价" << endl; }
};class Student : public Person {
public:virtual void BuyTicket() { cout << "学生买票-半价" << endl; }
};void Func(Person p)  //修改前:Person& p
{p.BuyTicket();
}
int main()
{Person ps;Student st;Func(ps);Func(st);return 0;
}


这个结果的产生原因和上面的原因是一致的,父类赋值给父类对象自然调用父类的成员函数、子类对象赋值给父类对象造成“切片”,将子类中的父类那一部分切出去,让父类对象调用

再修改代码,看结果:
#include <iostream>
using namespace std;class Person {
public:virtual void BuyTicket() { cout << "成人买票-全价" << endl; }
};class Student : public Person {
public:virtual void BuyTicket() { cout << "学生买票-半价" << endl; }
};void Func(Person* p)  //修改前:Person& p
{p->BuyTicket();
}
int main()
{Person ps;Student st;Func(&ps);  //修改前 Func(ps);Func(&st);  //修改前 Func(st);return 0;
}

使用指针的时候又根据指向对象的不同,调用出不同的结果

根据上面的代码结果,我们可以大概感知到多态就是根据不同继承关系的类对象,调用同一函数时产生了不同的行为。那么产生多态的条件是什么呢?


文章目录

  • 一、多态引入
        • 修改上面的代码,观察结果:
        • 我们再修改代码,思考结果:
        • 再修改代码,看结果:
  • 二、多态构成的条件
        • 回顾上面的代码,感受多态的条件
        • 析构函数的重写-析构函数名统一会被处理成destructor()
        • C++11 新语法:override 和 final
        • 抽象类
            • 1、概念
            • 2、 抽象类代码感知
  • 总结


二、多态构成的条件

重写的概念

  • 两个函数分别在子类和父类的作用域中
  • 函数名 / 返回值 / 参数都必须相同
  • 两个函数必须是虚函数 (被virtual 修饰的类成员函数成为虚函数
  • 注意:参数只看类型是否相同,不看缺省值

多态构成的条件

  • 需要在继承中使用
  • 必须使用父类的引用或者指针调用虚函数
  • 被调用的函数必须是虚函数,且子类必须对父类的虚函数进行重写
回顾上面的代码,感受多态的条件
#include <iostream>
using namespace std;
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;
}

这时候指针p,它指向什么类型,就调用该类型的对象里面的成员

析构函数的重写-析构函数名统一会被处理成destructor()

只有子类 Student 的析构函数重写了 Person 的析构函数,下面的 delete 对象调用析构函
数,才能构成多态,才能保证 p1 和 p2 指向的对象正确的调用析构函数。
函数名处理成destructor() 才能满足多态:
如果父类的析构函数为虚函数,此时子类析构函数只要定义,无论是否加virtual关键字,
都与父类的析构函数构成重写,虽然父类与子类析构函数名字不同。虽然函数名不相同,
看起来违背了重写的规则,其实不然,这里可以理解为编译器对析构函数的名称做了特殊处
理,编译后析构函数的名称统一处理成destructor。

class Person {
public:virtual ~Person() {cout << "~Person()" << endl;}
};
class Student : public Person {
public:virtual ~Student() { cout << "~Student()" << endl; }
};
int main()
{Person* p1 = new Person;Person* p2 = new Student;delete p1;delete p2;return 0; 
}


所以当父类的指针指向子类的对象时,一定需要将父类的析构函数写成虚函数,如果不定义成虚函数,那么delete p的时候,就会只父类的析构函数(切片),不会调用子类的析构函数,造成内存泄漏

C++11 新语法:override 和 final

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

override: 检查子类虚函数是否重写了父类某个虚函数,如果没有重写编译报错

抽象类
1、概念

在虚函数的后面写上 “= 0” ,则这个函数为纯虚函数包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象子类继承后也不能实例化出对象,只有重写纯虚函数,子类才能实例化出对象。纯虚函数规范了子类必须重写,另外纯虚函数更体现出了接口继承。

2、 抽象类代码感知
#include <iostream>
using namespace std;class Car
{
public:virtual void Drive() = 0;//	// 实现没有价值,因为没有对象会调用他//	/*virtual void Drive() = 0//	{//		cout << " Drive()" << endl;//	}*/
};
class Benz :public Car
{
public:virtual void Drive()  //重写父类的纯虚函数{cout << "Benz-舒适" << endl;}
};
class BMW :public Car
{
public:virtual void Drive() //重写父类的纯虚函数{cout << "BMW-操控" << endl; }
};
void Test()
{Car* pBenz = new Benz;pBenz->Drive();Car* pBMW = new BMW;pBMW->Drive();
}
int main()
{Test();return 0;
}


总结

今天我们熟悉了多态的构成条件以及多态的使用,下一次我们详细聊聊多态的原理,感知一下为什么会出现这样的结果?编译器是怎么做得?

更多推荐

C++中多态的使用和建立条件

本文发布于:2023-12-04 04:13:34,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1659721.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:条件   多态

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!