07-1 多态的使用
Tips:多态分为静态多态和动态多态,但是在一般情况下,“多态“表示的是动态多态。
现在创建三个类,Animal
、Cat
和Dog
。分别在各自的类内创建Speak()
函数表示说话。之后,创建一个doSpeak()
函数表示说话的动物。具体如下:
#include<iostream>
#include<string>
using namespace std;
class Animal
{
public:
void speak()
{
cout << "一只动物在说话。" << endl;
}
};
class Cat :public Animal
{
public:
void speak()
{
cout << "喵喵喵" << endl;
}
};
class Dog :public Animal
{
public:
void speak()
{
cout << "汪汪汪" << endl;
}
};
void doSpeak(class Animal& p)
{
p.speak();
}
int main()
{
class Cat cat;
class Dog dog;
doSpeak(cat);
doSpeak(dog);
return 0;
}
运行结果:(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)
一只动物在说话。
一只动物在说话。
在上面的实例中,我们传入了两只动物,cat
和dog
,但是调用doSpeak()
函数,执行的不是对应类中的Speak()
函数,而是类Animal
中的Speak()
函数。
首先,在cpp的继承之中,允许父子之间的类型转换,包括引用和指针,不需要强制类型转换。
-
强制类型转换:eg:
int main() { char a = 'a'; int b = (int)a; cout << b << endl; return 0; }
运行结果:(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)
97
在这里,对象
a
是一个char
类型的对象,但是通过强制转换,可以将char
类型赋值给int
类型。
但是在函数doSpeak()
中,传入的内容是引用类型传入的Animal
。执行doSpeak(cat);
的时候,相当于执行了一句:class Animal& p = cat;
。
因为传入的是Animal
,而不是具体的动物。虽然在后续传入的是Cat
,但是cpp进行了类型转换,这只Cat
已经被转换为了Animal
。
这就是静态多态:地址早绑定。即:函数地址在程序编译的时候就确定了。
如果想执行传入什么动物就叫什么动物,那么这个函数地址就不能提前绑定,需要在程序运行阶段绑定。也就是地址晚绑定。
我们试一下修改的代码:
#include<iostream>
#include<string>
using namespace std;
class Animal
{
public:
virtual void speak()
{
cout << "一只动物在说话。" << endl;
}
};
class Cat :public Animal
{
public:
void speak()
{
cout << "喵喵喵" << endl;
}
};
class Dog :public Animal
{
public:
void speak()
{
cout << "汪汪汪" << endl;
}
};
void doSpeak(class Animal& p)
{
p.speak();
}
int main()
{
class Cat cat;
class Dog dog;
doSpeak(cat);
doSpeak(dog);
return 0;
}
运行结果:(环境:Windows11(arm/Apple M VM)/Visual Studio 2022/Debug/arm64)
喵喵喵
汪汪汪
这两段代码的区别:在基类的speak()
函数定义前加上了:virtual
。这样,这个函数就变成了虚函数。由于传入的对象不同,才决定执行的函数不同。
-
总结:
-
动态多态的满足条件:
-
需要存在继承关系。
-
派生类需要重写基类的某个函数(重写的要求:函数名称相同、参数列表、返回值类型完全相同)。
-
基类中被重写的函数需要是虚函数(关键字:
virtual
)
-
-
动态多态的使用:
- 基类的指针或者引用指向派生类的对象。
-
:-)