前言
本文主要介绍一下C++语言中多态的相关知识。多态是建立在继承之上的,本人认为继承使编写代码有了结构,多态则使这个结构变得可拓展,更加绚丽多彩。
多态
定义什么的我就不放了,直接说自己的见解。
多个拥有部分共同性质的对象可以继承同一个父类,在减少了代码编写量的同时保证了逻辑体系的完整,实现了“一个接口,多种方法。”
多态通过new关键子实现,在使用new的时候相当于重新申请了一个空间,当使用空间结束后要用delete四、释放空间。此时我们需要针对new和malloc进行一下区分:
-
new/delete是C++运算符,需要编译器支持。malloc/free是库函数,需要头文件支持。
-
使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算。而malloc则需要显式地指出所需内存的尺寸。
-
new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换,故new是符合类型安全性的操作符。而malloc内存分配成功则是返回void * ,需要通过强制类型转换将void*指针转换成我们需要的类型。
-
new内存分配失败时,会抛出bac_alloc异常。malloc分配内存失败时返回NULL。
-
new会先调用operator new函数,申请足够的内存(通常底层使用malloc实现)。然后调用类型的构造函数,初始化成员变量,最后返回自定义类型指针。delete先调用析构函数,然后调用operator delete函数释放内存(通常底层使用free实现)。 malloc/free是库函数,只能动态的申请和释放内存,无法强制要求其做自定义类型对象构造和析构工作。
#include <iostream>
using namespace std;
int main(){
int* p = (int*)malloc(sizeof(int));
p[0] = 100;
free(p);
int* n = new int;
*n = 200;
delete n;
int* a = new int[10];
a[8] = 10;
delete[] a;
return 0;
}
对象是使用多态最多的。
#include <iostream>
using namespace std;
class People{
public:
People(){
cout << "People" << endl;
}
~People(){
cout << "~People" << endl;
}
};
int main(){
People* p = (People*)malloc(sizeof(People));
free(p);
People* n = new People;
delete n;
return 0;
}
函数重写/函数覆盖
- 父类定义虚函数;
- 子类实现父类的虚函数。
#include<iostream>
using namespace std;
class People {
public:
People() {
cout << "People" << endl;
}
~People() {
cout << "~People" << endl;
}
virtual void play() { //虚函数
cout << "吃饭 睡觉 打豆豆" << endl;
}
};
class Student: public People {
public:
void play() { //函数覆盖
cout << "王者 吃鸡 英雄联盟" << endl;
}
};
int main() {
Student s;
s.play();
return 0;
}
多态的实现
- 函数重写/函数覆盖
- 父类指针指向子类对象,并且调用子类的重写函数(运行的就是子类函数)
#include <iostream>
using namespace std;
class People {
public:
People() {
cout << "People" << endl;
}
~People() {
cout << "~People" << endl;
}
virtual void play() {
cout << "people play" << endl;
}
};
class Student :public People {
public:
void play() {
cout << "student play" << endl;
}
};
class Farmer :public People {
public:
void play() {
cout << "Farmer play" << endl;
}
};
int main()
{
Student s;
People* p = (People*)&s;
p->play();
return 0;
}
在这里不得不提一下函数隐藏和函数重写的区别了。上面的代码用的就是函数重写,因为父类的的函数有virtual。如果父类没有virtual则程序输出People play,此时是函数隐藏,即子类的函数隐藏。至于为什么是子类的函数隐藏?因为p的类型是People*。
多态的应用场景
- 存储
int main() {
Student s;
Student s2;
Student s3;
Farmer f1;
Farmer f2;
Farmer f3;
People p1;
People p2;
People p3;
People* vector[10] = {&s, &s, &s3, &f1, &f2, &f3, &p1, &p2, &p3};
return 0;
}
通过将多个对象存储在一个对象类型的数组里。通过这种方式也可以用循环批量调用对象的方法。
- 参数
我们可以通过多态向一个函数里传递参数。
void printInfo(People* p) {
p->play();
}
静态成员
静态成员变量
静态成员变量属于类,不属于对象。
要在类外初始化。
public:
static int water;
};
给静态成员变量赋值:
int People::water = 100;
静态成员函数
静态成员函数不能访问非静态成员属性。
public:
static void drink() {
water--;
}
缺省函数参数
缺省函数参数只能将可以缺省的参数写道右面。
#include <iostream>
using namespace std;
class People {
public:
People(int a, int b = 0, int c =2) {
cout << "People" << endl;
}
};
int main()
{
People(1);
return 0;
}