当前位置: 首页 > news >正文

威海建设信息网站/互联网营销师培训大纲

威海建设信息网站,互联网营销师培训大纲,加密的网站使用jmeter做压测,光谷做网站推广哪家好不加virtual,只能访问成员变量,不能访问成员函数 文章目录 前言1 虚函数与多态不用虚函数的多态使用虚函数的多态 2 C虚函数注意事项 构成多态的条件C虚函数注意事项构成多态的条件什么时候声明虚函数 3 C虚析构函数的必要性总结 前言 本节阐述C中的多态…

不加virtual,只能访问成员变量,不能访问成员函数

文章目录

  • 前言
  • 1 虚函数与多态
    • 不用虚函数的多态
    • 使用虚函数的多态
  • 2 C++虚函数注意事项 构成多态的条件
    • C++虚函数注意事项
    • 构成多态的条件
    • 什么时候声明虚函数
  • 3 C++`虚析构函数`的必要性
  • 总结


前言

本节阐述C++中的多态(polymorphism)虚函数(virtual function),首先来阐明一下什么是多态。

  • C++中的多态指通过一个基类的指针或引用来调用其派生类对象的函数,从而实现对不同子类对象的不同处理。
  • 基类指针指指向最原始那个类对象的指针。
  • 虚函数是C++中一种函数的声明方式,虚函数就是为了解决当一个基类指针调用派生子类对象函数的时候,执行的是派生子类对象的函数和参数,而不是基类的。

1 虚函数与多态

不用虚函数的多态

#include <iostream>
using namespace std;// 基类A
class A{
protected:int a_A;
public:// A(int a):a_A(a){}void display();
};
void A::display(){cout<< "this is class A\n"<<"and value = \n"<< a_A<<endl;
}
// 派生类 B
class B : public A{
public:B(int a): A(a){}void display();
};
void B::display()
{cout<< "this is class B\n"<<"and value = \n"<< a_A<<endl;
}int main()
{A *p = new A(1);p->display();p = new B(2);p->display();return 0;
}

运行结果:

this is class A
and value = 1
this is class A
and value = 2

我们常态思维:如果指针指向了派生类对象,就应该使用派生类的成员变量和成员函数。但是该实例告诉我们,当基类指针p指向派生类B的对象的时候,虽然使用了派生类B的成员变量,但是却没有使用它的成员函数,导致输出结果啥也不是。

也就是说,通过基类指针只能访问派生类的成员变量,但是不能访问派生类的成员函数。

为了消除上述尴尬,让基类指针能够访问派生类的成员函数,C++增加了虚函数(Virtual Function)。使用虚函数非常简单,只需要在函数声明前面增加virtual关键字。

使用虚函数的多态

#include <iostream>using namespace std;class A{
protected:int a_A;
public:A(int a):a_A(a){}virtual void display();
};void A::display(){cout<< "this is class A\n"<<"and value = "<< a_A<<endl;
}class B : public A{public:B(int a): A(a){}void display();
};void B::display()
{cout<< "this is class B\n"<<"and value = "<< a_A<<endl;
}int main()
{A *p = new A(1);p->display();p = new B(2);p->display();return 0;
}

运行结果:

this is class A
and value = 1
this is class B
and value = 2

只需要在函数申明的前面加上virtual便可以解决上述所说的尴尬。更全面地实现了多态。
C++提供多态的目的是:可以通过基类指针对所有派生类(包括直接派生和间接派生)的成员变量和成员函数进行“全方位”的访问,尤其是成员函数。如果没有多态,我们只能访问成员变量

2 C++虚函数注意事项 构成多态的条件

C++虚函数注意事项

  • 只需要在虚函数的声明处加上virtual关键字,函数定义处可以加也可以不加
  • 只需要将基类中的函数声明为虚函数,这样所有派生类中具有遮蔽关系的同名函数都将自动成为虚函数。
  • 当在基类中定义了虚函数,但是在派生类没有定义新的函数来遮蔽次函数,那么将使用基类的虚函数。
  • 只有派生类的虚函数覆盖基类的虚函数(函数原型相同)才能构成多态(通过基类指针访问派生类函数)。
  • 构造函数不能是虚函数。对于基类的构造函数,他仅仅是在派生类构造函数中被调用,这种机制不同于继承。也就是说,派生类不继承基类的构造函数,将构造函数声明为虚函数没有任何意义;另外还有一种原因:C++中的构造函数用于创建对象时进行初始化工作,在执行构造函数之前对象尚未创建完成,虚函数表尚不存在,也没有指向虚函数表的指针,所以此时无法查询虚函数表,也就不知道要调用哪个构造函数。
  • 析构函数可以声明为虚函数,而且有时候必须要声明为虚函数

构成多态的条件

  • 必须存在继承的关系;
  • 继承关系中必须有同名的虚函数,并且他们是覆盖关系(函数原型相同);
  • 存在基类的指针,通过该指针调用虚函数;
  • 通过基类指针只能访问从基类继承过去的成员,不能访问派生类新增加的成员

什么时候声明虚函数

  • 首先看成员函数所在的类是否会作为基类。
  • 然后看成员函数在类的继承后有无可能被更改功能。

3 C++虚析构函数的必要性

析构函数用于在销毁对象时进行清理工作,可以声明为虚函数,且有时候必要声明为虚函数。

#include <iostream>using namespace  std;
// 基类 A
class A{
protected:char* str;public:A(){str = new char[100];cout<<"A contructor"<<endl;}~A(){delete str;cout<<"A destructor"<<endl;}
};
// 派生类 B
class B: public A{
private:char* name;
public:B(){name = new char[100];cout<<"B contructor"<<endl;}~B(){delete name;cout<<"B destructor"<<endl;}
};int main()
{A *pa = new B();delete pa;cout<<"================="<<endl;B *pb = new B();delete pb;return 0;
}

在上述代码中,首先定义了基类A,定义了A的成员变量(protected)str,在构造函数中为str申请一块内存,在析构函数中销毁str的这块内存;定义了A的派生类B,B中定义成员变量name,在B的构造函数中为name申请一块内存,并在B的析构函数中销毁这块内存。 在main函数中,首先定义一个基类A的指针指向派生类B的对象,然后释放这个指针。又定义一个指向派生类的指针指向派生类的对象,再释放该指针。

运行结果:

A contructor
B contructor
A destructor
=================
A contructor
B contructor
B destructor
A destructor

很显然出现了问题:内存泄露,基类指针指向派生类对象,在释放基类指针的时候,并没有执行派生类的析构函数(没有释放掉派生类中为成员变量name申请的内存空间),只是执行基类的析构函数。

为什么delete pa; 不会调用派生类的析构函数?
这里的析构函数不是虚函数,通过指针访问非虚函数的时候,编译器会根据指针的类型来确定要调用的函数;也就是说,指针指向哪个类就调用哪个类的函数,。因此pa是基类的指针,不管它指向基类对象还是派生类的对象,始终都只调用基类的析构函数。

为什么delete pb; 会同时调用派生类和基类的析构函数?
pb是派生类的指针,编译器会根据它的类型匹配到派生类的析构函数,在执行派生类的析构函数的过程中,又会调用基类的析构函数。派生类析构函数始终会调用基类的析构函数,这个过程是隐式完成的

解决方法:将基类的析构函数声明为虚函数。

class A{
public:A();virtual ~A();
protected:char* str;
};

运行结果:

A contructor
B contructor
B destructor
A destructor
=================
A contructor
B contructor
B destructor

基类虚析构函数 联动:当基类的析构函数声明为虚函数之后,派生类的析构函数也会自动称为虚函数。此时编译器会忽略指针的类型,而根据指针的指向来选择函数;也就是说,指针指向哪个类就调用哪个类的函数。pa和pb都指向派生类的对象,所以会调用派生类的析构函数,继而再调用基类的析构函数。因此也就解决了内存泄漏问题。

因此多半情况下,基类的析构函数是虚函数


总结

使用了虚函数之后,我们就可以通过定义一个基类指针,遍历所有的派生类成员变量和成员函数,很大程度简化了代码的复杂度。

http://www.jmfq.cn/news/5364721.html

相关文章:

  • 企业网站建设话术/大连网络推广公司哪家好
  • 湖北省建设厅投标报名官方网站/广东深圳疫情最新
  • 建设工程资质录入是在那个网站/新手怎么做seo优化
  • 山西中色十二冶金建设有限公司网站/海南百度推广公司有哪些
  • 广东工程建设监理有限公司网站/网络视频营销平台
  • 武汉麦诺信网站建设/关键词排名seo
  • 易企秀 旗下 网站建设/seo资讯网
  • 留学中介网站建设方案/商品seo优化是什么意思
  • 工程建设公司网站/雅思培训机构哪家好机构排名
  • 计算机网站建设体会/建立免费个人网站
  • 天津建设工程评标专家网站/镇江关键字优化品牌
  • 网站集约化建设 统一出口/北京广告公司
  • 我为什么电商要学网站建设/seo长尾快速排名
  • 建设企业高端网站/网站查询
  • 建设网站图/青岛seo排名收费
  • 数字资产交易网站建设/百度高搜
  • 怎么写网站建设的说明/广告公司营销策划方案
  • 达濠市政建设有限公司网站/百度推广登陆平台
  • 安徽省建设业协会网站/宁波网站推广公司价格
  • 广东建设工程造价管理协会网站/百度助手官网
  • 网站建设需要那些人才/seo优化方案项目策划书
  • 德宏北京网站建设/百度人工服务热线电话
  • 东西湖区城乡建设局网站/免费的网页入口
  • 网站建设排名政务/国外网站加速
  • 泉州哪家网站建设公司好/整站优化方案
  • 西安网站建设xamokj/国际新闻界
  • av网站正在建设中/网络营销和传统营销的区别和联系
  • 连云港东海网站建设/跨境电商平台推广
  • 中国建设银行北京分行门户网站公告/搜索引擎营销的方法不包括
  • 查建设项目开工是看建委网站吗/全网营销代运营