C++的动态联编与静态联编【转载】

C++的动态联编与静态联编【转载】

【摘要】:本文阐述了静态联编和动态联编的概念和区别,通过具体实例分析了实现动态联编的条件,指出了虚函数是实现动态联编的基础。

【关键词】:静态联编;动态联编;虚函数

在C++中,联编是指一个计算机程序的不同部分彼此关联的过程。按照联编所进行的阶段不同,可分为两种不同的联编方法:静态联编和动态联编。

    1. 静态联编

 

  静态联编是指联编工作在编译阶段完成的,这种联编过程是在程序运行之前完成的,又称为早期联编。要实现静态联编,在编译阶段就必须确定程序中的操作调用(如函数调用)与执行该操作代码间的关系,确定这种关系称为束定,在编译时的束定称为静态束定。静态联编对函数的选择是基于指向对象的指针或者引用的类型。其优点是效率高,但灵活性差。

 

//例1:静态联编

#include"iostream.h"

class A
{
    

public: void f()
{
  cout
<<"A"<<"";
} }; class B: public A {
public: void f(){cout<<"B"<<endl;} }; Void main() {
  A
* pa=NULL;   A a;
B b;   pa
=&a; pa->f();   pa=&b; pa->f(); }

 

该程序的运行结果为:A   A

从例1程序的运行结果可以看出,通过对象指针进行的普通成员函数的调用,仅仅与指针的类型有关,而与此刻指针正指向什么对象无关。要想实现当指针指向不同对象时执行不同的操作,就必须将基类中相应的成员函数定义为虚函数,进行动态联编。

 

2. 动态联编

动态联编是指联编在程序运行时动态地进行,根据当时的情况来确定调用哪个同名函数,实际上是在运行时虚函数的实现。这种联编又称为晚期联编,或动态束定。动态联编对成员函数的选择是基于对象的类型,针对不同的对象类型将做出不同的编译结果。C++中一般情况下的联编是静态联编,但是当涉及到多态性和虚函数时应该使用动态联编。动态联编的优点是灵活性强,但效率低。

动态联编规定,只能通过指向基类的指针或基类对象的引用来调用虚函数,其格式为:指向基类的指针变量名->虚函数名(实参表)或基类对象的引用名.虚函数名(实参表)

实现动态联编需要同时满足以下三个条件:

①    必须把动态联编的行为定义为类的虚函数。

②    类之间应满足子类型关系,通常表现为一个类从另一个类公有派生而来。

③    必须先使用基类指针指向子类型的对象,然后直接或者间接使用基类指针调用虚函数。

//例2:动态联编

#include"iostream.h"

classA

{
public:

Virtual void f()//虚函数

{cout<<"A"<<"";}};

class B:public A

{
public:
Virtual void f()//虚函数
{cout<<"B"<<endl;}

};

void main()

{ 
A* pa=NULL;

A a; B b;
pa=&a;
pa->f();
pa=&b;
pa->f();

}

 

该程序的运行结果为:A  B

从例2程序的运行结果可以看出,将基类A中的函数f定义为虚函数后,当指针指向不同对象时执行了不同的操作,实现了动态联编。

3. 动态联编分析

 动态联编要求派生类中的虚函数与基类中对应的虚函数具有相同的名称、相同的参数个数和相同的对应参数类型、返回值或者相同,或者都返回指针或引用,并且派生类虚函数所返回的指针或引用的基类型是基类中虚函数所返回的指针或引用的基类型的子类型。如果不满足这些条件,派生类中的虚函数将丢失其虚特性,在调用时进行静态联编。

例3:通过指向基类的指针来调用虚函数

#include"iostream.h"

Class base

{

public:

virtual void fun1(){cout<<"base fun1"<<endl;}

virtual void fun2(){cout<<"base fun2"<<endl;}

void fun3(){cout<<"base fun3"<<endl;}

void fun4(){cout<<"base fun4"<<endl;}

};

Class derived:public base

{
    public:

Virtual void fun1(){cout<<"derived fun1"<<endl;}

Virtual void fun2(intx){cout<<"derived fun2"<<endl;}

Virtual void fun3(){cout<<"derived fun3"<<endl;}

Void fun4(){cout<<"derived fun4"<<endl;}};

Void main()

{
    base*pb;

derive dd;

pb=&d;//通过指向基类的指针来调用虚函数
pb->fun1();
pb->fun2();
pb->fun3();
pb->fun4();

}

 

该程序的运行结果:

Derived fun1 base fun2 base fun3 base fun4

 

本例中函数fun1在基类base和派生类derived中均使用了关键字virtual定义为虚函数,并且这两个虚函数具有相同的参数个数、参数类型和返回值类型。因此,当指针pb访问fun1函数时,采用的是动态联编。函数fun2在基类base和派生类de-rived中定义为虚函数,但这两个虚函数具有不同的参数个数。函数fun2丢失了其虚特性,在调用时进行静态联编。函数fun3在基类base中说明为一般函数,在派生类derived中定义为虚函数。在这种情况下,应该以基类中说明的成员函数的特性为标准,即函数fun3是一般成员函数,在调用时采用静态联编。函数fun4在基类base和派生类derived中均说明为一般函数,因此基类指针pb只能访问base中的成员。

 

 

例4:通过基类对象的引用来调用虚函数

#include"iostream.h"

Class CPoint

{
    public:

CPoint(doublei,doublej){x=i;y=j;}

Virtual double Area(){
   return 0.0;}

private:

double x,y;

};

Class CRectangle:public CPoint

{
    public:

CRectangle(double i,double j,double k,double l);

Double Area(){
    return w*h;}

private:

double w,h;

};

CRectangle::CRectangle(double i,double j,double k,double l):CPoint(i,j)

{  w=k;h=l;  }

Void fun(CPoint &s)

{  cout<<s.Area()<<endl;  }//通过基类对象的引用来调用虚函数

Void main()

{

CRectangle rec(3.0,5.2,15.0,25.0);

fun(rec);

}

 

该程序的运行结果为:375

 例4中的成员函数Area在基类CPoint中使用了关键字virtual定义为虚函数,在派生类CRectangle中定义为一般函数,但是进行了动态联编,结果为15*25即375。这是因为一个虚函数无论被公有继承多少次,它仍然保持其虚特性。在派生类中重新定义虚函数时,关键字virtual可以写也可不写,但为了保持良好的编程风格,避免引起混乱时,应写上该关键字。

4. 小结

    从以上四个例子中可以看出:虚函数是实现多态的基础,是实现动态联编的必要条件之一。动态联编要靠虚函数来实现,虚函数要靠动态联编的支持。两者相辅相成,缺一不可。

转载于:https://www.cnblogs.com/yep3575/p/3499322.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/109943.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Python识别图片中的文字「建议收藏」

    Python识别图片中的文字「建议收藏」不知道大家有没有遇到过这样的问题,就是在某个软件或者某个网页里面有一篇文章,你非常喜欢,但是不能复制。或者像百度文档一样,只能复制一部分,这个时候我们就会选择截图保存。

    2022年4月29日
    91
  • vscode新建文件,默认为html[通俗易懂]

    vscode新建文件,默认为html[通俗易懂]虽然还没达到理想目标,不过还是有进步步骤如下图文字版打开vscode–选择文件–首选项–设置到达设置页面文件(14)–找到要复制代码–复制,在加个html效果如下图右下脚由纯文本变为html…

    2022年8月22日
    23
  • 浙江python信息技术教材_人工智能、Python…浙江省三到九年级将使用信息技术新修订教材…

    浙江python信息技术教材_人工智能、Python…浙江省三到九年级将使用信息技术新修订教材…浙江省教研室相关负责人表示,目前根据现行的高中教材,对小学、初中的老教材进行了修订,新教材将于今年9月投入使用,最新的线上教师培训也刚刚结束。扣哒世界作为全球最大的中小学人工智能和Python代码编程教学平台,已经从2019年开始系统支持浙江省中小学人工智能和Python代码编程师资培训。根据浙江省最新的教材目录,从小学三年级一直到九年级,内容都有不同程度的调整。三年级新增了“信息社会”和“网络生…

    2022年5月16日
    36
  • Python动态爬虫爬取京东商品评论[通俗易懂]

    Python动态爬虫爬取京东商品评论[通俗易懂]Python动态爬虫爬取京东商品评论1.概述京东商城是Python爬虫初学者试手的经典平台,反爬虫程度较低,但评论采取了动态加载的方式,爬取京东商品评论是学习动态爬虫的一个极佳方法。动态爬虫,即针对动态加载JSON文件网页的爬虫,其原理与静态爬虫没有本质区别,只是不爬取所见的静态目标网页,而是寻找该网页所加载的JSON文件,爬取JSON文件中的内容。2.目标观察观察京东具体商品评论页面:点击商品评价页:发现商品评价翻页的url不改变,可推测出其采用动态加载的方式,同时,会发现直接获取该

    2022年7月26日
    8
  • 用pywinauto抓取微信公众号

    用pywinauto抓取微信公众号我试图用pywinauto抓取PC端微信中的公众号信息,但是碰到了大坑了。

    2022年5月18日
    76
  • query指定范围提取数据_嵌套查询和子查询

    query指定范围提取数据_嵌套查询和子查询repeater嵌套查询。代码如下:代码usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Web;usingSystem.Web.UI;usingSystem.Web.UI.WebControls;usingSystem.Data;namespa…

    2022年10月10日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号