/*
一、基本含义
在学习 C++知识的过程中,对于动态多态的理解不是很深,今天又将笔记翻找出来,结合网上的相关知识,复习一下。多态按字面的意思就是多种形态。当类之间存在因继承关系形成的层次结构时,可以用到多态。函数重载、运算符重载属于静态多态。 这里要学习理解的重点是动态多态。关于动态多态,可以这样理解:1.父类中写一个成员函数(本质还是成员函数),只是在函数类型前加上一个virtual关键字;2.让子类继承父类,并在子类中重写这个函数,函数名、返回值类型、参数类型及个数必须完全一样(这点不同于重载);并且,参数可有可无,有都有,无都无,有必须以引用或指针方式。3.调用时,哪个类调用就执行那个函数。父类的指针或引用指向子类的对象。
二、原理
C++动态多态性主要是通过虚函数在子类中重写实现的。动态多态与非动态多态的实质区别就是函数地址是早绑定还是晚绑定。如果函数的调用,在编译器编译期间就可以确定函数的调用地址,并产生代码,是静态的,就是说地址是早绑定的。如果函数调用的地址不能在编译期间确定,需要在运行时才确定,则是动态的,这就属于晚绑定。动态多态的优点是"一个接口,多种方法",程序在运行时才决定调用的具体函数,达到接口重用的目的。接口重用是动态多态的根本目的。
总结一下:动态多态的条件 1、有继承关系 2、子类要重写父类的虚函数(重写:返回值同、函数名同、参数同,不同于重载)3、父类中的virtual关键字必须写上,子类中可写可不写 。
三、使用方法
声明父类指针,利用该指针指向任意一个子类对象,调用相应的虚函数(或重写的虚函数),可以根据指向子类的不同而实现调用不同成员函数的目的。也就是一再强调的,父类的对象指针或引用,指向子类对象。
四、下面通过一个例子(在VS2019通过)加深理解:*/
#include<iostream>
#include<string>
using namespace std;
class FatherClass { //声明一个父类
public:
virtual void print() { //虚函数(被调用时输出父类标识)
cout << "This is FatherClass!" << endl;
};
};
class SonClassOne :public FatherClass {
public:
void print() { //重写父类虚函数,被调用时输出子类标识
//没有写 virtual,由于继承父类虚函数,写不写virtual都是虚函数,
//也可再被继承后重写;
cout << "This is SonClassOne!" << endl;
};
};
class SonClassTwo :public FatherClass {
public:
void print() { //重写父类虚函数,被调用时输出子类标
cout << "This is SonClassTwo!" << endl;
};
};
class GrandSonClass :public SonClassOne {
public:
void print() { //重写父类虚函数(它的父类SonClassOne又是FatherClass的子类)
//(被调用时输出子类标识)
cout << "This is GrandSonClass!" << endl;
};
};
void PrintToScreen(FatherClass* p) //父类指针作为显示函数(PrintToScreen)的参数
{
p->print(); //通过父类指针指向父类、子类、孙类对象
};
int main() {
FatherClass FC; //声明的父类对象
SonClassOne SCO; //声明的子类对象一
SonClassTwo SCT; //声明的子类对象二
GrandSonClass GSC; //声明的孙类对象
PrintToScreen(&FC); //父类指针指向对象FC
PrintToScreen(&SCO);//父类指针指向对象SCO
PrintToScreen(&SCT);//父类指针指向对象SCT
FatherClass* p;
p = &GSC;
PrintToScreen(p);//父类指针指向对象GSC
//上述四个对象都通过PrintToScreen函数的参数"p"
//即父类指针(FatherClass* p)指向父类、子类、
//孙类对象被调用,达到使用一个接口函数显示了
//不同类对象的结果;当然前提是这些类之间存在
//继承关系。
system("pause");
return 0;
}
// 输出结果如下,与程序目的一致
//This is FatherClass!
//This is SonClassOne!
//This is SonClassTwo!
//This is GrandSonClass!
//请按任意键继续. . .