c++多态

2022-11-23  本文已影响0人  arkliu

多态的基本概念

#include <iostream>
#include<string>
using namespace std;

class Parent{
    public:
        int m_id = 0;
        void show() {
            cout <<"Parent::show() m_id:"<<m_id<<endl;
        }
};

class Child:public Parent {
    public:
        int m_age;
        void show() {
            cout <<"Child::show() m_id:"<<m_id << "   m_age:"<<m_age<<endl;
        }

};

int main() {
    Child ch;
    ch.m_id = 10;
    ch.m_age = 20;
    Parent *par = &ch;
    par->show(); // 基类指针指向派生类对象,调用基类的函数
    return 0;   
}

image.png
class Parent{
    public:
        int m_id = 0;
        // 在基类的show方法前加上virtual关键字,声明为虚函数
        virtual void show() {
            cout <<"Parent::show() m_id:"<<m_id<<endl;
        }
};
image.png
#include <iostream>
#include<string>
using namespace std;

class Parent{
    public:
        int m_id = 0;
        // 在基类的show方法前加上virtual关键字,声明为虚函数
        virtual void show() {
            cout <<"Parent::show() m_id:"<<m_id<<endl;
        }
};

class Child:public Parent {
    public:
        int m_age;
        void show() {
            cout <<"Child::show() m_id:"<<m_id << "   m_age:"<<m_age<<endl;
        }

};

int main() {
    Child ch;
    ch.m_id = 10; ch.m_age = 20; //创建派生类对象并赋值
    Parent par;
    par.m_id = 33;
    
    Parent *ppar = &ch;
    ppar->show(); // Child::show() m_id:10   m_age:20
    ppar = &par;
    ppar->show(); // Parent::show() m_id:33
    return 0;   
}
image.png

\color{red}{注意:}

class Parent{
    public:
        int m_id = 0;
        // 在基类的show方法前加上virtual关键字,声明为虚函数
        virtual void show();
};

void Parent::show() {
    cout <<"Parent::show() m_id:"<<m_id<<endl;
}
Child ch;
ch.m_id = 10; ch.m_age = 20; //创建派生类对象并赋值
Parent par;
par.m_id = 33;

Parent *ppar = &ch;
ppar->Parent::show(); // Parent::show() m_id:33
image.png

虚析构函数

有时会让一个基类指针指向用 new 运算符动态生成的派生类对象;同时,用 new 运算符动态生成的对象都是通过 delete 指向它的指针来释放的。如果一个基类指针指向用 new 运算符动态生成的派生类对象,而释放该对象时是通过释放该基类指针来完成的,就会导致少释放一次, 看下面案例:

virtual_deconstruct.h

#pragma once
#include <iostream>
using namespace std;

class Parent
{
private:
public:
    Parent();
    ~Parent();
};

Parent::Parent()
{
    cout << "Parent() runs.." << endl;
}

Parent::~Parent()
{
    cout << "~Parent() runs.." << endl;
}

class Child : public Parent
{
private:
public:
    Child();
    ~Child();
};

Child::Child()
{
    cout << "Child() runs.." << endl;
}

Child::~Child()
{
    cout << "~Child() runs.." << endl;
}

测试代码

#include <iostream>
#include "virtual_deconstruct.h"

using namespace std;

int main() {
    Parent * p = new Child();

    delete p;
    return 0;
}
image.png

输出结果说明,\color{red}{delete p;只引发了 Parent类的析构函数被调用},没有引发 Child类的析构函数被调用。这是因为该语句是静态联编的,编译器编译到此时,不可能知道此时 p 到底指向哪个类型的对象,它只根据 p 的类型是 Parent* 来决定应该调用 Parent类的析构函数。

按理说,delete p;会导致一个 Child类的对象消亡,应该调用 Child类的析构函数才符合逻辑,否则有可能引发程序的问题

解决
更改改写上面程序中的 Parent类,在析构函数前加 virtual 关键字,将其声明为虚函数:

class Parent
{
private:
public:
    Parent();
    virtual ~Parent();
};

此时运行结果如下:


image.png
上一篇 下一篇

猜你喜欢

热点阅读