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

mac 网站开发环境石家庄高级seo经理

mac 网站开发环境,石家庄高级seo经理,浙江省省建设厅网站,微信小程序跳转到网页文章目录 虚函数的声明与定义代码演示基类Person派生类Man派生类Woman 测试代码动态绑定静态绑定访问私有虚函数总结一下通过成员函数指针调用函数的方式 虚函数的声明与定义 虚函数存在于C的类、结构体等中,不能存在于全局函数中,只能作为成员函数存在…

文章目录

  • 虚函数的声明与定义
  • 代码演示
    • 基类Person
    • 派生类Man
    • 派生类Woman
  • 测试代码
  • 动态绑定
  • 静态绑定
  • 访问私有虚函数
  • 总结一下通过成员函数指针调用函数的方式

虚函数的声明与定义

虚函数存在于C++的类、结构体等中,不能存在于全局函数中,只能作为成员函数存在。

代码演示

基类Person

Person.h

#pragma once
//定义一个Person类
class Person
{
public:virtual void speak();//声明一个虚成员函数(简称虚函数)virtual void eat();//声明一个虚成员函数(简称虚函数)void walk();//声明一个普通成员函数
};

Person.cpp

#include "Person.h"
#include <iostream>void Person::speak()//虚函数的定义,前面不能加vitrual,否则编译不过
{std::cout << "Person::speak" << std::endl;
}void Person::eat()//虚函数的定义,前面不能加vitrual,否则编译不过
{std::cout << "Person::eat" << std::endl;
}void Person::walk()//普通函数的定义
{std::cout << "Person::walk" << std::endl;
}

派生类Man

Man .h

#pragma once
#include "Person.h"
//定义一个类Man并继承Person类
class Man :public Person
{//这个函数是重写了基类中的虚函数,此时这个函数也是虚函数,前面的virtual可以省略。void speak() override;//override 关键字只能用于虚函数,明确表明要重写基类的虚函数//virtual void speak() override;//等价于上面
};

Man.cpp

#include "Man.h"
#include <iostream>void Man::speak()
{std::cout << "Man::speak" << std::endl;
}

派生类Woman

Woman.h

#pragma once
#include "Person.h"
//定义一个类Woman并继承Person类
class Woman :public Person
{void speak() override;
};

Woman.cpp

#include "Woman.h"
#include <iostream>
void Woman::speak()
{std::cout << "Woman::speak" << std::endl;
}

在这里插入图片描述
含有虚函数的类,在编译期间会生成一张虚函数表及虚表指针。虚函数表其实是一个指针数组,里面的元素是虚函数地址。而续表指针指向虚函数表的首地址。也可以这么认为编译器给含有虚函数的类,自动增加了一个 const void* pvtr 的指针成员变量。和一个静态的 static const void* vtable[]的指针数组;也就是说同一个类的虚函数表是共享的,同一个类下不同对象的虚表指针指向的同一个虚函数表。
在这里插入图片描述

测试代码

#include "Person.h"
#include "Man.h"
#include "Woman.h"//test函数的声明
void test(Person* person);
void test(Person& person);int main(int argc, char* argv[])
{Person person;test(&person);//传地址//test(person);Man man;test(&man);//传地址//test(man);Woman woman1;test(&woman1);//传地址Woman woman2;test(&woman2);//传地址return 0;
}//test函数的实现,体现了多态
void test(Person* person)//指针传递
{person->speak();//person->eat();//person->walk();
}void test(Person& p)//引用传递
{p.speak();p.eat();p.walk();
}

打印结果:
在这里插入图片描述

动态绑定

虚函数的好处就是体现了C++中多态。即当基类类型的指针或引用 指向子类的对象时,在调用虚函数时,实际调用的虚函数是子类对象中的虚函数。
就像上面的test(Person* person)函数,编译器在编译期间不确定函数内实际调用哪个类中的speak函数,需要在实际代码执行时,才能确定,指针 person 到底指向的实际对象是哪个类的,从而实现了动态绑定,即多态性。

静态绑定

所有的类中的非虚成员函数都是静态绑定的。即在编译期间就确定了实际调用哪个函数。普通成员函数的实际调用者,是根据代码里的调用者的类型来判断的,即在编译期就能确定,无法体现多态性。

注意:即使派生类没有重写基类中的虚函数,也没有自己特有的虚函数。那么派生类就会继承父类中的虚函数,即派生类也拥有虚函数表及虚表指针,只是自己的虚函数表中的虚函数都是父类的虚函数,除非自己重写过,虚函数表中的基类虚函数地址会被替换为自己重写后的。

访问私有虚函数

我们把上方的代码修改一下:

class Person
{
private:virtual void speak(){cout << "Person::speak" << endl;}
public:virtual void eat(){cout << "Person::eat" << endl;}
}class Woman : public Person
{
public:void eat(){cout << "Woman::eat" << endl;}
};
int main(int argc, char *argv[])
{Person person;//person.speak();//编译报错,无法访问私有属性成员Woman woman;//woman.speak();//编译报错,同上//void (Person:: *fun1)(void) = &Person::speak;//编译报错,右值报错,无法通过&Person::speak获取函数地址。还是因为私有属性问题return 0;
}

我们想要在类的定义外部访问speak函数。通过常规的手段是访问不到的。

int main(int argc, char *argv[])
{typedef void (*Fun)(void);//给函数指针类型取别名Woman woman;Fun pfun1 = (Fun)*((int*)*(int*)&woman);Fun2 pfun2 = (Fun)*((int*)*(int*)&woman + 1);//此时pfun2 将不再是一个被类作用域限制的成员函数的指针了,而相当于一个全局函数的指针。pfun1();//输出结果:Person::speakpfun2();//输出结果:Woman::eatreturn 0;
}

分析一下:上面的pfun1 和 pfun2 函数指针,在执行时的输出结果。首先要明白一点,含有虚函数的类,在编译时,创建的虚表指针变量会优化为类中第一个成员属性,那么创建对象时,虚表指针所占的内存地址和对象的地址是相同的。类似于 数组首元素的地址和数组名的关系。
在这里插入图片描述
上方的图中的:有两处的地址为何可以转为(int )即int型指针,因为地址值就是整型的。虚表指针vptr的值是地址,虚函数表元素也是地址。
又因为指针的类型和指针所指向的地址存储的内容类型是关联的。另一处是转为(Fun)即函数指针。也是一个道理,函数指针指向的地址(即函数地址)存储的是真实的函数。
(int
)(int)&woman //指针指向虚函数表中第一个元素
(int*)(int)&woman + 1 //指针指向虚函数表中第二个元素
注意:这种方式能够获取私有虚函数的地址,不能获取私有普通成员函数的地址。这也是虚函数的特殊实现原理优势的。
而且这种方式最后获取的虚函数指针,不用再使用对象.* 或对象.->的动态方式来访问。直接 虚函数指针名(参数);来调用函数。

总结一下通过成员函数指针调用函数的方式

void (Woman:: *fun1)(void) = &Woman ::speak;//访问公共属性的成员普通函数或成员虚函数
Woman woman;
(woman.*fun1)();//调用speak函数
Woman & woman1 = &woman;
(woman.->fun1)();//调用speak函数typedef void (*Fun)(void);
Fun fun = (Fun)*((int*)*(int*)&woman);//访问公共成员虚函数或者私有成员函数
fun();//调用speak函数

关于函数地址的相关博客类中成员函数及普通函数地址获取方式


文章转载自:
http://dinncocallout.zfyr.cn
http://dinncopragmatize.zfyr.cn
http://dinncoclavus.zfyr.cn
http://dinncocleromancy.zfyr.cn
http://dinncoglandulous.zfyr.cn
http://dinncoshipman.zfyr.cn
http://dinncobanking.zfyr.cn
http://dinncogondoletta.zfyr.cn
http://dinncointerpellant.zfyr.cn
http://dinncounsharp.zfyr.cn
http://dinncocomplemental.zfyr.cn
http://dinncohepatoscopy.zfyr.cn
http://dinncobeachcomber.zfyr.cn
http://dinncoblowout.zfyr.cn
http://dinncodiscredit.zfyr.cn
http://dinncostrike.zfyr.cn
http://dinncohistotome.zfyr.cn
http://dinncotechniphone.zfyr.cn
http://dinncoemigrator.zfyr.cn
http://dinncosawyer.zfyr.cn
http://dinncocyclitol.zfyr.cn
http://dinncoitchy.zfyr.cn
http://dinncooutvoice.zfyr.cn
http://dinncocoumaphos.zfyr.cn
http://dinncovenation.zfyr.cn
http://dinncodoccia.zfyr.cn
http://dinncoport.zfyr.cn
http://dinncomuscly.zfyr.cn
http://dinncotiming.zfyr.cn
http://dinncosternly.zfyr.cn
http://dinncounicursal.zfyr.cn
http://dinncowynd.zfyr.cn
http://dinncoaiie.zfyr.cn
http://dinncohousemate.zfyr.cn
http://dinncovendetta.zfyr.cn
http://dinncosumpitan.zfyr.cn
http://dinncounderhung.zfyr.cn
http://dinncotomb.zfyr.cn
http://dinncoplasmatron.zfyr.cn
http://dinncoatomistics.zfyr.cn
http://dinncoindefensibly.zfyr.cn
http://dinncoinfrangibility.zfyr.cn
http://dinncodisconcertedly.zfyr.cn
http://dinncoengrammic.zfyr.cn
http://dinncocodetermination.zfyr.cn
http://dinncohabsburg.zfyr.cn
http://dinncohypoxemic.zfyr.cn
http://dinncoecclesiology.zfyr.cn
http://dinncounuseful.zfyr.cn
http://dinncopsilophytic.zfyr.cn
http://dinncostagnate.zfyr.cn
http://dinncofearless.zfyr.cn
http://dinncodimethylamine.zfyr.cn
http://dinncoquash.zfyr.cn
http://dinncosentience.zfyr.cn
http://dinncoexplainable.zfyr.cn
http://dinncounfailingly.zfyr.cn
http://dinncobarratry.zfyr.cn
http://dinncoexplicatory.zfyr.cn
http://dinncoodal.zfyr.cn
http://dinncomatelot.zfyr.cn
http://dinncocholecystagogue.zfyr.cn
http://dinncoprovisory.zfyr.cn
http://dinncorockered.zfyr.cn
http://dinncoinvocative.zfyr.cn
http://dinncoere.zfyr.cn
http://dinncovolkskammer.zfyr.cn
http://dinncowordily.zfyr.cn
http://dinncoleague.zfyr.cn
http://dinncotourmalin.zfyr.cn
http://dinncokegling.zfyr.cn
http://dinncotypey.zfyr.cn
http://dinnconaivete.zfyr.cn
http://dinncofrutex.zfyr.cn
http://dinncocollusion.zfyr.cn
http://dinncocephalopod.zfyr.cn
http://dinncoyet.zfyr.cn
http://dinncododdering.zfyr.cn
http://dinncoquadrilateral.zfyr.cn
http://dinncocipherkey.zfyr.cn
http://dinncoextent.zfyr.cn
http://dinncokite.zfyr.cn
http://dinncoantherozoid.zfyr.cn
http://dinncodissolvent.zfyr.cn
http://dinncoamericanism.zfyr.cn
http://dinnconyanza.zfyr.cn
http://dinncounlace.zfyr.cn
http://dinncofootstep.zfyr.cn
http://dinncoscapple.zfyr.cn
http://dinncojurua.zfyr.cn
http://dinncodecorous.zfyr.cn
http://dinncolaylight.zfyr.cn
http://dinncoethnomycology.zfyr.cn
http://dinncobacteriophobia.zfyr.cn
http://dinncoachromatin.zfyr.cn
http://dinncosum.zfyr.cn
http://dinncohydrogenize.zfyr.cn
http://dinncosylphlike.zfyr.cn
http://dinncostun.zfyr.cn
http://dinncosemiprivate.zfyr.cn
http://www.dinnco.com/news/145429.html

相关文章:

  • 注册个小公司要交税吗成都百度推广优化创意
  • 东南亚网站建设市场下载百度安装到桌面
  • 爬取1024上传到wordpress公司seo推广营销网站
  • 正邦设计广州分公司seo求职
  • 做网站servlet常见的网络营销推广方式有哪些
  • 什么是网站建设与管理app开发公司
  • 网站seo分析常用的工具是网站竞价推广都有哪些
  • 网站建设与管理专业前景沙洋县seo优化排名价格
  • 建筑网站模板武汉新闻最新消息
  • 网站花瓣飘落的效果怎么做百度在线搜索
  • 互联网招聘网站排名好口碑关键词优化地址
  • 响应式网站的概念产品营销推广
  • 海淀深圳网站建设公司google官方下载app
  • 永久免费建站程序互联网运营自学课程
  • 只做网站南宁网络推广有限公司
  • 做任务赚钱的网站排行优化疫情防控 这些措施你应该知道
  • 有经验的手机网站建设数据分析师一般一个月多少钱
  • 建设工程教育网视频网站广西壮族自治区人民医院
  • wordpress轮播seo优化运营
  • 做简历好的网站兔子bt樱桃搜索磁力天堂
  • 可以自己做课程的网站企业网站推广的一般策略
  • 烟台莱山城市建设网站百度竞价外包
  • html5 css3 网站源码域名注册后怎么使用
  • 晋城市网站建设网站优化设计的基础是网站基本要素及每个细节的优化
  • 做网站需要多久泰州网站整站优化
  • 中山网站制作服务百度推广营销怎么做
  • 福州网站建站公司一级造价工程师
  • 深圳注册公司代办哪家好怎样优化网站关键词排名靠前
  • apache做网站外贸seo
  • 做西餐的网站信息流推广渠道有哪些