首页 > 编程 > C++ > 正文

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

2019-11-06 07:19:33
字体:
来源:转载
供稿:网友

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

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

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不是必须,系统会自动加一个virtualprivate: 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;};

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


上一篇:c++链表

下一篇:C++学习笔记

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选