结论:使用类指针调用成员函数时,普通函数由指针类型决定,虚函数由指针指向的实际类型决定
10年积累的成都做网站、网站制作经验,可以快速应对客户对网站的新想法和需求。提供各种问题对应的解决方案。让选择我们的客户得到更好、更有力的网络服务。我虽然不认识你,你也不认识我。但先做网站设计后付款的网站建设流程,更有涡阳免费网站建设让你可以放心的选择与我们合作。虚函数实现(内存布局)每个类在创建的时候构造一张虚函数表,该表是编译器在编译时设置的静态数组,每个表项存放虚函数的入口地址(即函数指针),发生虚函数调用时,通过函数指针所指向的函数来调用相应虚函数。
vptr长8个字节,用*(unsigned long *)obj取出后,因为虚表中每个元素(虚函数指针)在64位编译器下是8个字节,通过*((unsigned long *)vptr_addr+offset)即可获得每个函数的表项地址。
可以看到子类对父类虚函数进行重载时,基类指针指向子类实例的内存的虚函数表中,原父类虚函数已被子类虚函数覆盖,实际调用时,调用的是子类的虚函数。(注意:父类基函数在子函数前面)
如存在多重继承,则子类中存在多个虚函数表,子类自己的虚成员函数添加到第一个声名的虚函数表中
实现过程小结:通过对象内存中的vptr找到虚函数表vtbl,接着通过vtbl找到虚函数实现区域并调用
因为构造函数完成前,对象内存尚未初始化,vptr没有值,无法通过vptr找到虚函数实现代码区。
尽管构造函数不可以为虚函数,但是有些场景下我们确实需要 “Virtual Copy Constructor”。 “虚复制构造函数”的说法并不严谨,其只是一个实现了对象复制的功能的类内函数。 举一个应用场景,比如剪切板功能。 复制内容作为基类,但派生类可能包含文字、图片、视频等等。 我们只有在程序运行的时候才知道我们需要复制的具体是什么类型的数据。(例:在基类函数中声明virual Clone)
析构函数最好定义为虚函数用基类类型指针绑定派生类实例,析构的时候,如果基类析构函数不是虚函数,则只会析构基类,不会析构派生类对象,从而造成内存泄漏。为什么会出现这种现象呢,析构的时候如果没有虚函数的动态绑定功能,就只根据指针的类型来进行的,而不是根据指针绑定的对象来进行,所以只是调用了基类的析构函数;如果基类的析构函数是虚函数,则析构的时候就要根据指针绑定的对象来调用对应的析构函数了。
通过基类定义虚函数重载,使派生类对象删除时调用子类的虚析构函数,并子类析构函数执行完后自动执行父类析构函数
虚函数成为私有函数int main()必须声明为Base类的友元,否则编译失败。 编译器报错: ptr无法访问私有函数。 当然,如果把基类声明为public, 继承类为private,该问题就不存在了。
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧