什么是多态性?C++中如何实现多态? 多态的好处和注意事项有哪些?

多态的概念

多态性是指通过基类指针或引用调用派生类的函数,实现不同的行为。多态性可以提高代码的灵活性和可扩展性,使程序能够根据不同的对象类型执行不同的操作

多态的实现

主要通过虚函数实现多态,在基类中声明虚函数,在子类中重写这些虚函数。通过基类指针或引用调用虚函数时,实际调用的是派生类中重写的虚函数

cpp 复制代码
#include<iostream>
using namespace std;
class Animal
{
public:
    virtual void speak()
    {
        cout << "animal speak" << endl;
    }       {
};
class cat :public Animal
{
public:
    void speak()
    {
        cout << "cat speak" << endl;
    }        {
};
class dog :public Animal
{
public:
    void speak()
    {
        cout << "dog speak" << endl;
    }        {
};
int main() {
    Animal *a = new dog;   
    a->speak();//调用的是dog里的speak函数    
 //父类指针调用虚函数,先通过父类指针访问dog类的对象,
 //找到对象里的虚表指针,这个虚表指针指向的虚表是类dog的虚表,
//就上类dog的虚表中找speak,类dog重写了speak,所以调用的是子类的speak
    return 0;
}

每个包含了虚函数的类都包含一个虚函数表(存放虚函数指针的数组,就是存放的是虚函数的地址),调用虚函数,必须通过虚函数表找到虚函数的地址
只要类中有虚函数,那么类中就会多一个成员变量,这个成员变量就是虚函数表的指针,调用虚函数,先访问这个对象里的虚函数表指针,通过虚函数表指针找到虚函数那个数组,在遍历数组找到虚函数地址

多态的好处

  • 可以使代码更灵活,易于扩展和维护
  • 可以提高代码的复用性,减少代码的编写、

注意事项

虚函数的正确使用

在 C++ 中,实现多态的关键是虚函数。如果一个函数在基类中被声明为虚函数,那么在派生类中重写该函数时,函数名,参数,返回值必须完全一致。

cpp 复制代码
class Base {
public:
    virtual void func(int x) {
        std::cout << "Base func with int: " << x << std::endl;
    }
};
class Derived : public Base {
public:
    void func(int x) override {
        std::cout << "Derived func with int: " << x << std::endl;
    }
};

这里Derived类中的func函数正确地重写了Base类中的虚函数func。如果函数签名不一致,可能会导致函数隐藏而不是多态行为。例如,如果Derived类中的func函数参数列表与Base类中的不同,就会发生函数隐藏。

对象切片问题

当把派生类对象赋值给基类对象时,会发生对象切片。

cpp 复制代码
class Base {
public:
    int baseData;
    Base(int data) : baseData(data) {}
};
class Derived : public Base {
public:
    int derivedData;
    Derived(int base, int derived) : Base(base), derivedData(derived) {}
};
int main() {
    Derived d(1, 2);
    Base b = d;  // 对象切片发生在这里
    // 此时b只包含Base部分的数据,Derived部分的数据丢失
    return 0;
}

这种情况在多态中需要特别注意,因为如果希望通过基类指针或引用调用派生类的完整多态行为,对象切片会导致意外的结果。通常应该使用基类指针或引用来避免对象切片问题,例如Base& b = d;或Base* p = &d;。

相关推荐
捕鲸叉1 小时前
Linux/C/C++下怎样进行软件性能分析(CPU/GPU/Memory)
c++·软件调试·软件验证
涛ing3 小时前
23. C语言 文件操作详解
java·linux·c语言·开发语言·c++·vscode·vim
半桔3 小时前
栈和队列(C语言)
c语言·开发语言·数据结构·c++·git
阿猿收手吧!3 小时前
【Linux网络总结】字节序转换 收发信息 TCP握手挥手 多路转接
linux·服务器·网络·c++·tcp/ip
NOAHCHAN19873 小时前
怎么解决Visual Studio中两个cpp文件中相同函数名重定义问题
c++·visual studio
Ciderw3 小时前
Golang并发机制及CSP并发模型
开发语言·c++·后端·面试·golang·并发·共享内存
Uitwaaien544 小时前
51 单片机矩阵键盘密码锁:原理、实现与应用
c++·单片机·嵌入式硬件·51单片机·课程设计
小唐C++4 小时前
C++小病毒-1.0勒索
开发语言·c++·vscode·python·算法·c#·编辑器
Golinie5 小时前
【C++高并发服务器WebServer】-2:exec函数簇、进程控制
linux·c++·webserver·高并发服务器
课堂随想5 小时前
`std::make_shared` 无法直接用于单例模式,因为它需要访问构造函数,而构造函数通常是私有的
c++·单例模式