类和对象-多态-多态的基本语法
多态的基本语法
#include<iostream>
using namespace std;
//动物类
class Animal
{
public:
//虚函数
virtual void speak()
{
cout << "动物在说话" << endl;
}
};
//猫类
class Cat :public Animal
{
public:
void speak()
{
cout << "小猫在说话" << endl;
}
};
//执行说话函数
//地址早绑定在编译阶段确定函数地址
//如果想执行让猫说话,那么这个函数地址就不能提前绑定,需要在运行阶段进行绑定,地址晚绑定
void dospeak(Animal & animal) //Animal & animal = cat;
{
animal.speak(); //动物在说话
}
void test01()
{
Cat cat;
dospeak(cat);
}
int main() {
test01();
return 0;
}
// _ooOoo_ //
// o8888888o //
// 88" . "88 //
// (| ^_^ |) //
// O\ = /O //
// ____/`---'\____ //
// .' \\| |// `. //
// / \\||| : |||// \ //
// / _||||| -:- |||||- \ //
// | | \\\ - /// | | //
// | \_| ''\---/'' | | //
// \ .-\__ `-` ___/-. / //
// ___`. .' /--.--\ `. . ___ //
// ."" '< `.___\_<|>_/___.' >'"". //
// | | : `- \`.;`\ _ /`;.`/ - ` : | | //
// \ \ `-. \_ __\ /__ _/ .-` / / //
// ========`-.____`-.___\_____/___.-`____.-'======== //
// `=---=' //
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
// 佛祖保佑 永无BUG 永不修改 //
对于代码
virtual void speak()
{
cout << “动物在说话” << endl;
}
为什么要使用虚函数呢?
-
实现多态性:虚函数是实现多态性的关键。通过在基类中声明虚函数,派生类可以重写(override)这些函数。当基类指针或引用指向派生类对象时,通过虚函数调用将会根据实际对象的类型来决定调用哪个版本的函数。这种动态绑定在运行时进行,因此能够根据对象的实际类型来执行适当的代码,实现多态行为。
-
解决指针或引用切换问题:在面向对象设计中,经常会使用基类的指针或引用来管理派生类对象。如果函数不是虚函数,那么无论指针或引用的实际类型是什么,都只会调用基类的函数。而使用虚函数可以确保在通过基类指针或引用调用函数时,实际执行的是对象的派生类版本,从而确保了行为的多样性和灵活性。
-
实现动态绑定:虚函数机制通过将函数调用的绑定推迟到运行时,从而支持了动态绑定。这意味着编译器在编译阶段不会确定函数调用的确切版本,而是等到程序运行时根据对象的实际类型来确定。这种动态绑定是面向对象编程中多态性的关键特性之一,它使得程序能够更加灵活和易于扩展。
如果没有使用虚函数,即使通过 dospeak
函数传递了一个 Cat
对象,实际调用的仍然是基类 Animal
的 speak
函数,输出的是 “动物在说话”。而如果将 speak
函数声明为虚函数,在运行时就会根据 Cat
对象的实际类型调用 Cat
类的 speak
函数,输出 “小猫在说话”。这就是虚函数带来的动态多态性效果。
实现动态多态需要满足的条件
-
继承关系:动态多态通常通过基类和派生类的继承关系来实现。基类通常定义一个或多个虚函数,这些函数可以被派生类重写(覆盖)。
class Base { public: virtual void func() { // 基类的虚函数实现 } }; class Derived : public Base { public: void func() override { // 派生类的重写函数 } };
-
虚函数声明:在基类中声明虚函数。虚函数通过关键字
virtual
声明,并且可以在派生类中被重写。派生类可以选择性地使用override
关键字来显式地表明它正在重写基类中的虚函数。class Base { public: virtual void func(); // 虚函数声明 }; class Derived : public Base { public: void func() override; // 重写基类的虚函数 };
-
基类指针或引用:通过基类的指针或引用来调用虚函数,这样可以在运行时确定实际调用的函数版本。这是动态多态的关键,因为它允许程序根据对象的实际类型来调用适当的函数。
void someFunction(Base& obj) { obj.func(); // 使用基类引用调用虚函数 } int main() { Derived d; someFunction(d); // 传递派生类对象给基类函数 return 0; }
-
运行时类型信息(RTTI):C++中的动态多态性是通过运行时类型信息来实现的。在调用虚函数时,程序会检查对象的实际类型,并决定调用哪个版本的函数。这种行为称为动态绑定或后期绑定。
原文地址:https://blog.csdn.net/weixin_61839295/article/details/140491590
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!