C++之多态(静态多态+动态多态+虚函数+虚析构函数+多态原理[未完待续])

多态(静态多态+动态多态)
多态是面向对象的三大特征(封装,继承,多态)之一。
教科书定义:指相同对象接收不同消息或不同对象接到相同消息产生不同的动作。简单来说就是当发出一条命令时,不同的对象接收到同样的命令时,所做出的动作是不同的。

静态多态(早绑定)
如下代码,两个一样的函数名,但是参数不同,在调用时,程序会根据参数不同调用不同函数。因为程序很早就把这种情况编译进去,这就情况就叫静态多态。

class Rect
{
public:
    int calcArea(int width);
    int calcArea(int width, int height);
};

int main()
{
    Rect rect;
    rect.calcArea(10);
    rect.calcArea(10, 20);
    return 0;
}

动态多态(晚绑定)
动态多态必须以封装和继承为基础,动态多态起码要有两个类,一个是子类,一个是父类,当然也可以有三个类,只有有三个类的时候我们的动态多态才能表现的比较明显,以下代码为例

class Circle :public Shape
{
public:
    Circle(double r);
    double calcArea();
private:
    double m_dR;
};
double Circle::calArea()
{
    return 3.14*m_dR*m_dR;
};
double Rect::calcArea()
{
    return m_dWidth*m_dHeight;
};
int main()
{
    Shape *shape1 = new Circle(4,.0);
    Shape *shape2 = new Rect(3.0,5.0);
    shape1->calcArea();//用到的都是父类的计算面积,屏幕上会打印出claArea()
    shape2->calcArea();
    //....
    return 0;
}

可以利用virtual虚函数来实现多态。如下代码,输出的就是计算的圆的面积

class Shape
{
public:
    virtual double calcArea()//虚函数
    {
        cout << "clacArea" << endl;
        return 0;
    }
};

class Circle :public Shape
{
public:
    Circle(double r);
    virtual double calcArea();//virtual不是必须,系统会自动加一个virtual
private:
    double m_dR;
};

但是动态多态容易引起内存泄漏的问题,如下代码
代码1:

class Shape
{
public:
    Shape();
    virtual double calcArea();
};

class Circle :public Shape
{
public:
    Circle(int x, int y, double r);
    ~Circle();
    virtual double calcArea();
private:
    double m_dR;
    Coordinate *m_pCenter; //多定义了一个指针的数据成员
};

Circle::Circle(int x, int y, double r)
{
    m_pCenter = new Coordinate(x, y);
    m_dR = r;
}

Circle::~Circle
{
    delete m_pCenter;
    m_pCenter = NULL;
}

int main()
{
    Shape *shape1 = new Circle(3, 5, 4.0);
    shape1->calArea();
    delete shape1;//想借助父类的指针去销毁子类的指针时,会出问题,只执行父类的析构
    shape1 = NULL;
    return 0;
}

如上代码,我们在Circle中多定义了一个成员指针*m_pCenter,当我们在main()函数中delete shape1时,由于它是父类的指针,销毁时他只会调用父类的析构函数,而不会调用子类的析构函数,这就造成了内存的泄漏。这时我们要引入虚析构函数,同样是用virtual关键字修饰析构函数。代码示例如下:
代码1.1

class Shape
{
public:
    Shape();
    virtual ~shape();//虚析构函数
    virtual double calcArea();

};

class Circle :public Shape
{
public:
    Circle(int x, int y, double r);
    virtual ~Circle();
    virtual double calcArea();
private:
    double m_dR;
    Coordinate *m_pCenter; //多定义了一个指针的数据成员
};

这个时候我们再用代码1中的main()函数,这个时候我们再使用delete,如果我们这个时候在delete后面跟上父类指针的时候,父类指针指向的是哪个对象,那么哪个对象的析构函数就先得以执行,然后再执行父类的。这样就保证了内存不会泄漏。

同样vitual的使用也有一些限制
1.普通函数(全局函数)不能是虚函数,要是类中的成员函数。
2.静态成员函数不能是虚函数
3.内联函数不能是虚函数
4.构造函数不能是虚函数

虚函数的实现原理
先介绍一下函数指针:之前我们知道如果通过指针指向对象,我们叫他对象指针,那么指针当然也可以指向函数,函数的本质是一段二进制代码,它写在内存当中,我们可以通过指针来指向这段代码的开头,那么计算机就会从开头一直执行,直到函数的结尾,然后再返回。函数的指针和普通的指针本质上时一样的,如下图
这里写图片描述

class Shape
{
public:
    virtual double calcArea()//虚函数
    {
        return 0;
    }
protected:
    int m_iEge;
};

class Circle :public Shape
{
public:
    Circle(double r);
private:
    double m_dR;
};

我们看如上的代码,此时的虚函数如何实现呢?(等我搞懂了再说—–

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面是一个使用C++虚函数实现多态的代码示例: ```cpp #include <iostream> using namespace std; class A { public: virtual void foo() { cout << "A::foo()" << endl; } virtual ~A() { cout << "~A()" << endl; } }; class B : public A { public: void foo() { cout << "B::foo()" << endl; } ~B() { cout << "~B()" << endl; } }; int main() { A* p = new B(); p->foo(); delete p; return 0; } ``` 在这个示例中,类A和类B都有一个名为foo()的虚函数。当我们通过基类指针p调用foo()函数时,实际上会根据指针所指向的对象的类型来确定调用哪个类的foo()函数。这就是多态的实现原理。 输出结果为: ``` B::foo() ~B() ~A() ``` 可以看到,通过虚函数实现的多态,调用的是派生类B的foo()函数,而不是基类A的foo()函数。同时,析构函数也是虚函数,确保在删除指针p时,会先调用派生类B的析构函数,再调用基类A的析构函数。这是因为在C++中,如果基类的析构函数不是虚函数,那么通过基类指针删除派生类对象时,只会调用基类的析构函数,而不会调用派生类的析构函数。因此,为了确保正确的析构顺序,析构函数应该声明为虚函数。 请注意,虚函数只能在类的成员函数中声明,构造函数不能声明为虚函数。这是因为在创建对象时,需要先调用构造函数来初始化对象,而虚函数的机制是在运行时根据对象的类型来确定调用哪个函数,而构造函数在对象创建时就已经确定了。因此,构造函数不能声明为虚函数。 #### 引用[.reference_title] - *1* [虚函数实现多态原理](https://blog.csdn.net/qq_24309981/article/details/89102183)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [C++虚函数多态实现](https://blog.csdn.net/qq_27576655/article/details/124535530)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rocky0429

一块也是爱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值