C++之虚函数

本文介绍了C++中的虚函数如何实现多态,通过基类指针调用派生类的成员函数。同时讨论了构造函数不能是虚函数的原因,因为虚函数表在构造过程中生成。而对于析构函数,应使用虚析构函数以确保正确地销毁指向派生类的对象,防止内存泄漏。示例代码展示了虚析构函数在多态情况下的重要性。
摘要由CSDN通过智能技术生成

虚函数是C++中的一种成员函数,通过派生类对虚函数的重写来达到一个多态的目的。

多态:实现多态的话其实就是利用一个基类,用这个基类指针指向不同的派生类从而达到去实现派生类中的函数功能。

#include <iostream>

class Animal {
public:
    virtual void speak() { std::cout << "This is an animal." << std::endl; }
};

class Dog : public Animal {
public:
    void speak() { std::cout << "This is a dog. Woof!" << std::endl; }
};

class Cat : public Animal {
public:
    void speak() { std::cout << "This is a cat. Meow!" << std::endl; }
};

int main() {
    Animal* animal; //或者 Animal* god = new Dog()    
    Dog dog;
    Cat cat;

    animal = &dog; //This is a dog. Woof
    animal->speak();

    animal = &cat;//This is a cat. Meow!
    animal->speak();

    return 0;
}

为了能方便理解,我们创建了好几个类。让基类的指针指向派生类就是animal = &dog;然后用基类去调用。

上面这个是多态 的实现。

虚函数中为什么构造函数和析构函数一个能用虚函数一个不能用虚函数

构造函数不能采用虚函数,析构函数最好要用虚函数

构造函数是一个类构造最初执行的一个东西,而虚函数的调用需要一个虚函数表,虚函数表是在构造函数生成。你构造函数是虚函数,怎么调用呢?虚函数表都没有怎么调用构造函数呢?这样就陷入循环。

析构函数为什么要是虚函数?

当我们去实现多态的时候,一般是采用基类指针指向派生类来实现吧。(当然有些人会直接调用Dog dog;然后dog.speak();来实现狗叫,这当然可以,但是这个很麻烦不是吗?一般多态的写法是Animal* god = new Dog() 这样直接用基类指向派生类。其实这之中的god还是基类,只是指向dog类了而已。)这个时候我们去析构的话,假如虚函数不是虚函数,那么他肯定是析构自己的也就是基类的析构。不会去析构dog的类,这样是不是就内存泄漏了。只有让析构函数也采用虚函数的方法,才会像多态一样,指向派生类的析构函数。

#include <iostream>
using namespace std;

class Base
{
public:
    Base() { cout << "Output from the constructor of class Base!" << endl; };
   virtual ~Base() // 将基类析构函数声明为虚函数
    {
        cout << "Output from the destructor of class Base!" << endl;
    };
    virtual void DoSomething()
    {
        cout << "Do something in class Base!" << endl;
    };
};

class Derived : public Base
{
public:
    Derived() { cout << "Output from the constructor of class Derived!" << endl; };
    ~Derived()
    {
        cout << "Output from the destructor of class Derived!" << endl;
    };
    using Base::DoSomething; // 使用using声明语句引入基类同名函数
    void DoSomething() override
    {
        cout << "Do something in class Derived!" << endl;
    };
};

int main()
{
    Derived *pTest1 = new Derived(); //Derived类的指针
    pTest1->DoSomething();
    delete pTest1;

    cout << endl;

    Base *pTest2 = new Derived(); //Base类的指针
    pTest2->DoSomething();
    delete pTest2;

    return 0;
}
/*是虚函数的版本
Output from the constructor of class Base!
Output from the constructor of class Derived!
Do something in class Derived!
Output from the destructor of class Derived!
Output from the destructor of class Base!

Output from the constructor of class Base!
Output from the constructor of class Derived!
Do something in class Derived!
Output from the destructor of class Derived!
Output from the destructor of class Base!
*/
//不是虚函数的版本
/*Output from the constructor of class Base!
Output from the constructor of class Derived!
Do something in class Derived!
Output from the destructor of class Derived!
Output from the destructor of class Base!

Output from the constructor of class Base!
Output from the constructor of class Derived!
Do something in class Derived!
Output from the destructor of class Base!
*/

说说继承的事情吧

派生类是基于基类的吧,就好像儿子和父亲的关系,就算你单独创建派生类,你还是要创建基类的,没有父亲哪里来的儿子是吧,析构也是一样,派生类析构了,基类也要析构掉吧,你之前创建的啊。当我们没有用多态的方式的时候,比如Derived *pTest1 = new Derived(); 直接这样创建,无所谓是不是虚函数就正常的类。该怎么样就怎么样。

当我们用多态的时候,Base *pTest2 = new Derived(); 基类指向派生类,这个时候可以更加明显我们肯定要创建两个,基类和派生类。但是这个时候是基类Base 去指向派生类了,当我们没有吧析构函数设为虚函数的时候,就不会去实现析构函数的虚函数了,派生类也就没释放了。

C++中基类的析构函数为什么要用virtual虚析构函数_基类析构函数_yhc166188的博客-CSDN博客

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值