c++多态的含义

来源:互联网 发布:淘宝上的内购群能信吗 编辑:程序博客网 时间:2024/06/06 08:04

1.什么是多态?
(1)通过继承同一个基类,产生相关的不同派生类,与基类中同名的成员函数在不同的派生类中会与不同的实现,也就是说:一个接口、多种方法。
(2)多态是面向对象的重要技术之一,它是一种行为的封装,是同一个事物所表现出来的多种形态,简单地说就是:一个接口、多种形态。
(3)现在,运行时使用同一个成员名调用类对象的成员函数,会调用哪个对象的成员函数呢?这就是多态解决的问题。
2.多态的作用
(1)多态技术允许将基类指针或基类引用指向派生类
(2)把不同派生类的对象都当作基类对象来看待,可以屏蔽不同派生类之间的差异,从而写出通用的代码以适应需求的不断变化。
3.多态的分类
(1)多态分两类
》一种是静态多态,通过函数重载或者运算符重载实现。
》一种是动态多态,是只运行的时候的多态,通过虚函数与基类指针共同作用实现
4.在C++中如何实现多态
(1)在C++中,基类指针是指向基类对象的,如果用它来指向派生类对象,则进行指针类型转换(上行转换),将派生类指针转换为基类指针,所以改制真将会指向派生类对象中的积累部分,通过该指针是无法调用派生类对象中的成员函数的。
但是,虚函数突破了这一限制。在派生类的基类部分中,派生类的虚函数取代了基类原来的同名虚函数,因此在使用基类指针指向派生类对象后,使用该基类指针调用这个同名函数成员时就调用了派生类的虚函数。
(2)当把基类的某个成员函数声明为虚函数时,C++允许在其派生类中对该虚函数进行重新定义,赋予它新的功能,并且可以通过基类指针指向不同派生类的对象,来调用相应派生类中该同名虚函数。
由虚函数实现的动态多态性就是:同一类族中不同派生类对象,对同一函数调用作出不同的响应
(3)虚函数的使用方法如下:
》在基类中使用virtual关键字声明成员函数为虚函数(这样就可以在派生类中对该虚函数进行重新定义,赋予它新的功能)
》在派生类中重新定义此虚函数,要求函数名、形参列表、返回值类型均要与基类的虚函数相同,并根据具体需要重新定义它的函数题。
(4)C++规定,当一个成员函数被定义为虚函数后,其派生类中的同名函数都自动称为虚函数

“`
class base
{
public:
base(int a) :b(a){}
void my()
{
cout << “mybase” << endl;
}
virtual void fun()
{
cout << “i am a base” << endl;
}
private:
int b;
};

class child1 :public base
{
pubilc:
child1(int a1, int a2) : base(a1), c1(a2){}
void my()
{
cout << “mychild.” << endl;
}
virtual void fun()
{
cout << “I am a child1.” << endl;
}
private:
int c1;
};

class child2 :public base
{
pubilc:
child2(int a1, int a2) : base(a1), c2(a2){}
void my()
{
cout << “mychild.” << endl;
}
virtual void fun()
{
cout << “I am a child2.” << endl;
}
private:
int c2;
};

base *bptr;
child1 c1(10, 1);

child2 c2(10, 2);

bptr=&c1;//语句1:基类指针指向派生类对象child1
bptr->fun();//语句2,调用的是child1中的func;

c1.fun();//派生类
bptr->my();//基类
c1.my();//派生类

bptr = &c2;//语句3:基类指针指向派生类对象child2;
bptr->fun();//语句4:调用的是child2中的fun();

c2.fun();

bptr->my();//

5.虚函数与纯虚函数的区别与联系
(1)应该考虑:对成员函数的调用是通过对象名还是通过基类指针引用去访问。如果是后两者,则应当声明为虚函数。
(2)虚函数:如果一个类中定义了虚函数virtual,那么这个虚函数是被实现的,起作用就是为了让该虚函数在这个类中的派生类中被覆盖,被实现为不同的功能,从而结合基类指针以实现动态多态性。
(3)纯虚函数:有时定义一个虚函数时,并不定义其函数体,即他的函数体是空的,它的作用只是保留一个虚函数名,他关注的是接口的统一性,其具体功能实现由他的派生类完成。
比如:virtual float area(float a,float b)=0;

最后面的“=0”的作用仅仅只是告诉编译器这是一个纯虚函数。
纯虚函数只具有函数的名称,没有函数体,不具备函数功能,因此不能被调用。只有在其派生类中被重新定义后才具备函数功能,才能被调用。
如果在一个类中声明了纯虚函数,但是在其派生类中该纯虚函数并没有被定义,那么该虚函数在这个派生类中仍然为纯虚函数,仍然不具备函数的功能。
(4)抽象类与抽象基类:不用来定义对象而只作为一种基本类型用作被继承的类,称为抽象类;由于他经常用来作基类,故又称为抽象基类。凡是包含纯虚函数的类,都是抽象类,这种累不能直接生成对象,他的作用就是作为一个类族的共同基类,或者说为一个类族提供一个公共接口。
(5)需要说明的是,使用虚函数,系统要有一定的开销。当一个类中含有虚函数时,编译系统会为他构造一个虚函数指针vptr(4字节),同时这个虚函数指向一个虚函数表,虚函数表示一个指针数组,存放的是该类中的每个虚函数的入口地址。

6.虚析构函数的作用
(1)当派生类的对象从内存中撤销的时候,一般先调用派生类的析构函数释放该对象中的派生部分,再调用基类的析构函数释放该对象的基类部分,从而完整的释放该对象内存。
(2)但是,当用基类指针指向了一个派生类对象,即 base *bptr = new child;此时用delete bptr;来撤销bptr指向的动态存储空间时,只会执行基类的析构函数来释放该堆内存中的基类部分,但是并不会执行派生类的析构函数来释放该内存中的派生类部分。此时就会造成内存泄露现象。
(3)为了避免此类现象发生,我们将基类的析构函数声明为虚析构函数,这样就解决了上述问题(即先调用派生类的析构函数释放该动态空间中的派生类部分,在调用基类的析构函数释放该动态空间中的基类部分,从而能够完整的释放该堆内存。)
(4)如果将基类的析构函数声明为虚析构函数,那么该基类的所有派生类的析构函数都自动生成为虚析构函数。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 中国联通路由器网速慢怎么办 cpu铜触点掉落怎么办 商场没人气商户怎么办 58会员账号冻结怎么办 58账号冻结资金怎么办 超市买过期东西怎么办 淘宝没发货退款怎么办 申请退款发货了怎么办 51微投票异常怎么办 信用卡逾期收到律师函怎么办 淘宝商品被模仿怎么办 电脑数字间距大怎么办 有源码没有模块怎么办 花盆里有爬虫怎么办 家里有长条爬虫怎么办 有了网站源码后怎么办 第五人格闪退怎么办 超市买东西多收钱怎么办 王者荣耀换系统怎么办 夹娃娃夹子松怎么办 天猫魔盒遥控器没了怎么办 合约机被骗了怎么办 二手苹果合约机怎么办 手机系统老化了怎么办 手机显示电池老化怎么办 手机移动数据打不开怎么办 武汉移动大王卡怎么办 红米手机卡死了怎么办 红米手机死机怎么办 红米note5装卡大怎么办 手机卡二不显示怎么办 小米手机声音小怎么办 小米4手机屏幕失灵怎么办 安装包证书异常怎么办 安装包出现异常怎么办 红米手机按键失灵怎么办 红米手机内存不足怎么办 红米note2内存不足怎么办 信号强度-98dbm怎么办 小米mix2误触怎么办 指纹功能不能用怎么办