c++多态

1.多态性的概念

多态性指的是同一种操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在C++中,多态性通常通过虚函数来实现,它允许我们在基类中声明一个函数为虚函数,然后在派生类中对该函数进行重写(Override)。当我们使用基类指针或引用指向派生类对象并调用虚函数时,会根据实际对象的类型来调用相应的函数版本,从而实现多态性。

2.多态的构成条件

2.1多态的构成条件

  1. 必须通过基类的指针或者引用调用虚函数
  2. 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写

2.2虚函数

虚函数:即被virtual修饰的类成员函数称为虚函数。

2.3虚函数的重写

虚函数的重写(覆盖):派生类中有一个跟基类完全相同的虚函数(即派生类虚函数与基类虚函数的 返回值类型、函数名字、参数列表完全相同),称子类的虚函数重写了基类的虚函数

#include <iostream>  
  
// 基类  
class Base {  
public:  
    virtual void show() { // 虚函数声明  
        std::cout << "Base class show() called." << std::endl;  
    }  
};  
  
// 派生类  
class Derived : public Base {  
public:  
    void show() override { // 虚函数重写  
        std::cout << "Derived class show() called." << std::endl;  
    }  
};  
  
int main() {  
    Base* basePtr = new Derived(); // 基类指针指向派生类对象  
    basePtr->show(); // 通过基类指针调用虚函数,实现多态  
    delete basePtr; // 释放内存  
    return 0;  
}

2.4虚函数重写的两个例外

  • 协变
  1. 定义:协变是指基类与派生类虚函数返回值类型不同的情况。具体来说,当基类虚函数返回基类对象的指针或引用,而派生类虚函数返回派生类对象的指针或引用时,这种现象称为协变。

  2. 条件

    • 基类虚函数返回的是基类对象的指针或引用。
    • 派生类虚函数返回的是派生类对象的指针或引用,且与基类虚函数具有相同的函数名、参数列表。
  3. 示例

    class Base {  
    public:  
        virtual Base* fun() { /* ... */ }  
    };  
      
    class Derived : public Base {  
    public:  
        virtual Derived* fun() override { /* ... */ } // 协变示例  
    };

    在这个例子中,Derived::fun() 重写了 Base::fun(),并且返回类型从 Base* 协变为 Derived*

  • 析构函数的重写
  1. 定义:如果基类的析构函数被声明为虚函数,那么无论派生类的析构函数是否加virtual关键字,它都会与基类的析构函数构成重写关系,尽管它们的函数名不同。

  2. 特殊处理:编译器对析构函数的名称做了特殊处理,在编译后析构函数的名称会被统一处理成destructor,这样即便函数名在源代码层面不同,也会构成重写。

  3. 重要性:析构函数的重写对于多态性至关重要。当使用基类指针或引用删除派生类对象时,如果基类的析构函数不是虚函数,就可能不会调用派生类的析构函数,导致资源泄露或其他未定义行为。通过将基类的析构函数声明为虚函数,可以确保在删除派生类对象时正确调用其析构函数。

  4. 示例:

    class Person {  
    public:  
        virtual ~Person() { /* ... */ }  
    };  
      
    class Student : public Person {  
    public:  
        ~Student() override { /* ... */ } // 析构函数重写示例  
    };

    在这个例子中,Student 类的析构函数重写了 Person 类的析构函数。注意,在 C++11 及以后的版本中,可以使用 override 关键字来显式指示重写意图,这有助于编译器检查代码的正确性

3.抽象类

在虚函数的后面写上 =0 ,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口 类),抽象类不能实例化出对象。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生 类才能实例化出对象。纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承。

4.多态的原理

4.1虚函数表

#include<iostream>
using namespace std;
class Base
{
public:
	virtual void Func1()
	{
		cout << "Func1()" << endl;
	}
private:
	int _b = 1;
};
int main()
{
	Base d;
	cout << sizeof(d) << endl; //结果为8
	return 0;
}

除了_b成员,还多一个__vfptr放在对象的前面,对象中的这个指针我们叫做虚函数表指针(v代 表virtual,f代表function)。一个含有虚函数的类中都至少都有一个虚函数表指针,因为虚函数的地址要被放到虚函数表中,虚函数表也简称虚表。

4.2多态的原理

class Person {
public:
 virtual void BuyTicket() { cout << "买票-全价" << endl; }
};
class Student : public Person {
public:
 virtual void BuyTicket() { cout << "买票-半价" << endl; }
};
void Func(Person& p)
{
 p.BuyTicket();
}
int main()
{
 Person Mike;
 Func(Mike);
 
 Student Johnson;
 Func(Johnson);
 return 0;
}

  • 24
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值