C++中的静态绑定和动态绑定
- 格式:docx
- 大小:42.31 KB
- 文档页数:4
SDP: Session Description Protocol(会话描述协议)(RFC2327)1.概述SDP也是MMUSIC工作组的一个产品,在MBONE内容中用得很多。
其目的就是在媒体会话中,传递媒体流信息,允许会话描述的接收者去参与会话。
SDP基本上在internet上工作。
他定义了绘画描述的统一格式,但并不定义多播地址的分配和SDP消息的传输,也不支持媒体编码方案的协商,这些功能均由下层传送协议完成.典型的会话传送协议包括:SAP(Session Announcement Protocol 会话公告协议),SIP,RTSP,HTTP,和使用MIME的E-Mail.(注意:对SAP只能包含一个会话描述,其它会话传诵协议的SDP可包含多个绘画描述) SDP包括以下一些方面:1)会话的名称和目的2)会话存活时间3)包含在会话中的媒体信息,包括:媒体类型(video, audio, etc)传输协议(RTP/UDP/IP, H.320, etc)媒体格式(H.261 video, MPEG video, etc)多播或远端(单播)地址和端口4)为接收媒体而需的信息(addresses, ports, formats and so on)5)使用的带宽信息6)可信赖的接洽信息(Contact information)2.协议Session description //格式及举例v= (protocol version) //v=0o= (owner/creator and session identifier). //o=<用户名><会话id><版本><网络类//型><地址类型><地址>//o=sname 1234567890 0987654321 IN//IP4 126.15.64.3s= (session name) //会话名i=* (session information) //会话信息u=* (URI of description) //u=/staff/sdp.pse=* (email address) //e=zte@(general text如:王生)//或e=Mr. Wang<wang@> p=* (phone number) //p=+86-0755-********-7110(wang)//or p=+1 617 253 6011c=* (connection information -如已经包含在所有媒体中则该行不需要)//c=<网络类型><地址信息><连接地址>//多点会议包括TTL//连接地址: <base multicast//address>/<ttl>/<number of addresses>//c=IN IP4 224.2.13.23/127//c=IN IP4 224.2.1.1/127/3b=* (bandwidth information) //b=<修改量(CT Conference Total//IAS Application-specific Max)>:<带宽//值(kb/s)>//b=CT:120One or more time descriptions (see below)z=* (time zone adjustments) //时区调整k=* (encryption key) //k=<方法>:<密钥>或k=<方法>a=* (zero or more session attribute lines) //a=<属性> 或a=<属性>:<值>Zero or more media descriptions (see below)各行严格按顺序,其中:时间描述:t= (time the session is active) //<开始时间><结束时间>,单位秒,十//进制NTP//t=2873397468 2873404969 r=* (zero or more repeat times) //<重复时间><活动持续时间//以开始时刻为参考的偏移列表>单位秒//r=604800 3666 90000 或写成//r=7d 1h 0 25h媒体描述:m= (media name and transport address) //m=<媒体><端口><传送><格式列表>//m=audio 49170 RTP/A VP 0 3//协议为RTP,剖面为A VP//参考rtp-parameters.txti=* (media title媒体称呼) //c=* (connection information –如已经包含在会话级描述则为可选)b=* (bandwidth information) //同ck=* (encryption key) //会话级为摸认值,同ca=* (zero or more media attribute lines) //两种形式:(也同c)(见后说明)//a=<attribute>如:// a=recvonly//a=<attribute>:<value>注:v,o,s,t,m为必须的,其他项为可选。
C++语言中的虚函数研究作者:徐启丰胡勇万玉成来源:《现代电子技术》2010年第04期摘要:虚函数是面向对象的C++语言中的一个非常重要的概念。
它充分体现了面向对象思想中的继承和多态性这两大特性,动态绑定是C++中实现多态的一个重要途径,虚函数是动态绑定的基础。
通过深入分析VC++编译器实现虚函数的汇编代码。
给出在继承下的实现模型,并结合实例,在汇编语言层次研究了多态性的实现机理,揭示了虚函数和动态绑定的本质。
关键词:虚函数;多态性;绑定;构造函数中图分类号:TP312文献标识码:A文章编号:1004-373X(2010)04-154-03Study of Virtual Function in C++XU Qifeng,HU Yong,WANG Yucheng(Xuzhou Air Force College,Xuzhou,221000,China)Abstract:Virtual Function is an important concept of object oriented language C++.It presents the Inheritance and Polymorphism of the idea in object oriented language,dynamic binding is an important approach to realize polymorphism in C++ and virtual function is its foundation,this paper investigates the realization mechanism of virtual function in assemble language in VC++.According to inheritance relationship,the realize model of polymorphism is studied by example and in assemble language,and reveals the essence of virtual function and dynamic binding .Keywords:virtual function;polymorphism;bind;constructor0 引言多态性是面向对象程序设计语言继数据抽象和继承之后的第三个基本特征[1,2],在C++语言中,多态性是用虚函数来实现的[3,4],如果某类中的一个成员函数被说明为虚函数,该类被称为多态类,这就意味着该成员函数在派生类中可以有不同的实现,当用一个基类指针或引用指向一个继承类对象调用虚函数的时候,实际调用的是继承类版本的虚函数。
C语⾔与JAVA的区别是什么(推荐)⾸先来说说他们各⾃的历史:C语⾔的发展历史C语⾔的发展颇为有趣。
它的原型ALGOL 60语⾔。
(也成为A语⾔)1963年,剑桥⼤学将ALGOL 60语⾔发展成为CPL(Combined Programming Language)语⾔。
1967年,剑桥⼤学的Matin Richards 对CPL语⾔进⾏了简化,于是产⽣了BCPL语⾔。
1970年,美国贝尔实验室的Ken Thompson将BCPL进⾏了修改,并为它起了⼀个有趣的名字“B语⾔”。
意思是将CPL语⾔煮⼲,提炼出它的精华。
并且他⽤B语⾔写了第⼀个UNIX操作系统。
⽽在1973年,B语⾔也给⼈“煮”了⼀下,美国贝尔实验室的D.M.RITCHIE在B语⾔的基础上最终设计出了⼀种新的语⾔,他取了BCPL的第⼆个字母作为这种语⾔的名字,这就是C语⾔。
为了使UNIX操作系统推⼴,1977年Dennis M.Ritchie 发表了不依赖于具体机器系统的C语⾔编译⽂本《可移植的C语⾔编译程序》。
1978年Brian W.Kernighian和Dennis M.Ritchie出版了名著《The C Programming Language》,从⽽使C语⾔成为⽬前世界上流⾏最⼴泛的⾼级程序设计语⾔。
1988年,随着微型计算机的⽇益普及, 出现了许多C语⾔版本。
由于没有统⼀的标准,使得这些C语⾔之间出现了⼀些不⼀致的地⽅。
为了改变这种情况,美国国家标准研究所(ANSI)为C语⾔制定了⼀套ANSI标准, 成为现⾏的C语⾔标准 3.C语⾔的主要特点。
C语⾔发展迅速, ⽽且成为最受欢迎的语⾔之⼀, 主要因为它具有强⼤的功能。
许多著名的系统软件, 如DBASE Ⅲ PLUS、DBASE Ⅳ都是由C 语⾔编写的。
⽤C语⾔加上⼀些汇编语⾔⼦程序, 就更能显⽰C语⾔的优势了,象PC- DOS 、WORDSTAR 等就是⽤这种⽅法编写的。
编程语言的选择:动态语言和静态语言的优缺点编程语言的选择在软件开发中起着至关重要的作用。
在选择编程语言时,开发人员需要考虑如何平衡项目的需求、团队的技能和偏好、以及所选语言的优缺点。
其中,其中一个关键区分是动态语言和静态语言。
在本文中,我们将探讨两种类型语言的优缺点以及在实际开发中的应用。
动态语言指的是在运行时进行类型检查和绑定的编程语言,其中包括常见的Python、JavaScript和Ruby等。
与之相对的是静态语言,它在编译时进行类型检查和绑定,例如Java、C++和C#等。
以下是这两种类型语言的优缺点:动态语言的优点:1.灵活性:动态语言对类型要求相对宽松,可以在运行时灵活的改变对象的属性和方法。
2.代码简洁:通常来说,相比较于静态语言,动态语言的代码更为灵活,简洁,易于阅读和书写。
3.快速开发:由于动态语言通常有更少的语法限制和更高的表现力,因此它们可以更快地创建原型并进行迭代。
动态语言的缺点:1.运行时错误:由于类型检查是在运行时进行的,因此很难在编译或者静态分析阶段找出潜在的错误,这可能导致一些运行时的错误。
2.性能不足:动态语言通常比静态语言慢,因为它需要在运行时进行更多的工作,比如类型检查和动态绑定。
3.可维护性:动态语言的灵活性可能导致代码的可维护性较差,尤其是在大型项目中,可能出现类型难以追踪的问题。
静态语言的优点:1.性能优秀:静态语言在编译时进行类型检查,因此在运行时可以更快地执行,消耗更少的资源。
2.可维护性:由于静态语言在编译时进行类型检查,因此可以更早地发现潜在的错误,提高代码的可维护性。
3.代码更可预测:静态语言的严格类型约束和编译时检查可以使代码更加可预测,降低潜在的运行时错误。
静态语言的缺点:1.开发效率低:相比动态语言,静态语言通常需要更多的代码来表达相同的逻辑,因此开发效率相对较低。
2.代码冗余:由于静态语言需要显式地声明类型,在某些情况下可能会导致代码冗余,使代码看起来更为复杂。
8:下列多重继承时的二义性问题如何解决?class A{ //类A的定义public:void print () {cout<<"Hello, this is A"<<endl;}};class B{ //类B的定义public:void print () {cout<<"Hello, this is B"<<endl;}};class C : public A, public B{ //类C由类A和类B共同派生而来public:void disp () {print ();}//编译器无法决定采用A类中定义的版本还是B类中的版本};解答:若两个基类中具有同名的数据成员或成员函数,应使用成员名限定来消除二义性,如:void disp () {A: : print () ; //加成员名限定A::}print()但更好的办法是在类C中也定义一个同名print函数,根据需要调用A::还是Bprint(),从而实现对基类同名函数的隐藏::9:下列公共基类导致的二义性如何解决?class A{ //公共基类public: //public 成员列表void print(){cout << "this is x in A: " <<endl;}class B: public A{};class C: public A{};class D : public B, public C{};void main(){D d;//声明一个D类对象dA* pa=(A*) &d; //上行转换产生二义性d.print () ; //print ()具有二义性,系统不知道是调用B类的还是C类的print ()函数}注意:把子类的指针或引用转换成基类指针或引用是上行转换,把基类指针或引用转换成子类指针或引用是下行转换。
明必须放在类的内部 D. 类与类之间的友元关系不能被继承12. 在下面几项中,运算符在C++ 中不能被重载的是( c ) 。
A. && B. ~ C. ? : D. ++13. 在下面的说法中,不正确的一句是( a ) 。
A. 类的友元函数是类的特殊成员函数,它对所有的类成员、保护成员和私有成员享有完全访问特权 B. 一个类的友元类中的成员函数都是这个类的友元函数C. 适用于类成员函数和数据的访问控制同样适应于枚举和嵌套类D. 与结构类似,类也可以互相嵌套,适用于嵌套结构的规则也适用于嵌套类14. 下列叙述中,正确的是D. 对象数组的生存期结束之后,系统为数组中的每个元素调用一次析构函数15. 有如下两个类定义class XX{ private: double x1;protected: double x2;public: double x3;};class YY:protected XX{private:double y1;protected:double y2;public:double y3;};在类YY中保护成员变量的个数是( 4 )。
16. 以下哪个基类中的成员函数表示纯虚函数( c ) 。
A. virtual int vf(int) ; B. void vf(int) =0; C. virtual void vf( ) = 0; D. virtual void vf(int) { }17. C++ 的运算符函数的返回类型( a) A. 不能是void类型 B. 不可以是int类型C. 可以是任意类型 D.不可以是float类型18. 进行文件操作时需要包含 a.文件。
A. fstream.h B. ostream.h C. stdio.h D. stdlib.h19. 下列程序段中包含4个函数,其中具有隐含this指针的是( d )int fun1();class Test{public:int fun2();friend int fun3();static int fun4();};D)fun420. (30)下列代码声明了3个类class Person{};class Student:public Person{};classUndergraduate:Student{};下列关于这些类之间关系的描述中,错误的是dA)类Person是类Undergraduate 的基类B)类Undergraduate从类Student公有继承C)类Student是类Person的派生类D)类Undergraduate是类Person的派生类1. ( a ) 不是面向对象系统所包含的要素。
C++复习资料选择题PTA2-1下列函数中,(C)不能重载。
(2分)A.成员函数B.非成员函数C.析构函数D.构造函数2-2下列对重载函数的描述中,(A )是错误的。
(2分)A.重载函数中不允许使用默认参数B.重载函数中编译根据参数表进行选择C.不要使用重载函数来描述毫无相干的函数D.构造函数重载将会给初始化带来多种方式2-3设A为自定义类,现有普通函数int fun(A& x)。
则在该函数被调用时:C (2分) A a;Func(a);A.将执行复制构造函数来初始化形参xB.仅在实参为常量时,才会执行复制构造函数以初始化形参xC.无需初始化形参xD.仅在该函数为A类的友元函数时,无需初始化形参x2-4类成员的默认访问属性是:A(2分)A.privateB.protectedC.publicD.以上答案都不对2-5所有类都应该有:C (2分)A.构造函数B.析构函数C.构造函数和析构函数D.以上答案都不对析构函数可以返回:D(2分)A.指向某个类的指针B.某个类的对象C.状态信息表明对象是否被正确地析构D.不可返回任何值2-7对于以下关于友元的说法D (2分)A.如果函数fun被声明为类A的友元函数,则该函数成为A的成员函数B.如果函数fun被声明为类A的友元函数,则该函数能访问A的保护成员,但不能访问私有成员C.如果函数fun被声明为类A的友元函数,则fun的形参类型不能是A。
D.以上答案都不对2-8对于类之间的友元关系:D (2分)A.如果类A是类B的友元,则B的成员函数可以访问A的私有成员B.如果类A是类B的友元,则B也是A的友元。
C.如果类A是类B的友元,并且类B是类C的友元,则类A也是类C的友元。
D.以上答案都不对。
2-9友元的作用是A (2分)A.提高程序的运用效率B.加强类的封装性C.实现数据的隐藏性D.增加成员函数的种类2-10给定以下类声明,哪个成员函数可能改变成员变量data? D(2分)class A {public:void f1 (int d);void f2 (const int& d);{data=d;}void f3 (int d) const;private:int data;};A.f1B.f2D.f1和f22-1关于动态绑定的下列描述中,(D)是错误的。
SDP: Session Description Protocol(会话描述协议)(RFC2327)1.概述SDP也是MMUSIC工作组的一个产品,在MBONE内容中用得很多。
其目的就是在媒体会话中,传递媒体流信息,允许会话描述的接收者去参与会话。
SDP基本上在internet上工作。
他定义了会话描述的统一格式,但并不定义多播地址的分配和SDP消息的传输,也不支持媒体编码方案的协商,这些功能均由下层传送协议完成.典型的会话传送协议包括:SAP(Session Announcement Protocol 会话公告协议),SIP,RTSP,HTTP,和使用MIME的E-Mail.(注意:对SAP 只能包含一个会话描述,其它会话传送协议的SDP可包含多个会话描述)SDP包括以下一些方面:1)会话的名称和目的2)会话存活时间3)包含在会话中的媒体信息,包括:媒体类型(video, audio, etc)传输协议(RTP/UDP/IP, H.320, etc)媒体格式(H.261 video, MPEG video, etc)多播或远端(单播)地址和端口4)为接收媒体而需的信息(addresses, ports, formats and so on)5)使用的带宽信息6)可信赖的接洽信息(Contact information)2.协议Session description //格式及举例v= (protocol version) //v=0o= (owner/creator and session identifier). //o=<用户名><会话id><版本><网络类//型><地址类型><地址>//o=sname 1234567890 0987654321 IN//IP4 126.15.64.3s= (session name) //会话名i=* (session information) //会话信息u=* (URI of description) //u=/staff/sdp.pse=* (email address) //e=zte@(general text如:王生)//或e=Mr. Wang<wang@> p=* (phone number) //p=+86-0755-********-7110(wang)//or p=+1 617 253 6011c=* (connection information -如已经包含在所有媒体中则该行不需要)//c=<网络类型><地址信息><连接地址>//多点会议包括TTL//连接地址: <base multicast//address>/<ttl>/<number of addresses>//c=IN IP4 224.2.13.23/127//c=IN IP4 224.2.1.1/127/3b=* (bandwidth information) //b=<修改量(CT Conference Total//IAS Application-specific Max)>:<带宽//值(kb/s)>//b=CT:120One or more time descriptions (see below)z=* (time zone adjustments) //时区调整k=* (encryption key) //k=<方法>:<密钥>或k=<方法>a=* (zero or more session attribute lines) //a=<属性> 或a=<属性>:<值>Zero or more media descriptions (see below)各行严格按顺序,其中:时间描述:t= (time the session is active) //<开始时间><结束时间>,单位秒,十//进制NTP//t=2873397468 2873404969 r=* (zero or more repeat times) //<重复时间><活动持续时间//以开始时刻为参考的偏移列表>单位秒//r=604800 3666 90000 或写成//r=7d 1h 0 25h媒体描述:m= (media name and transport address) //m=<媒体><端口><传送><格式列表>//m=audio 49170 RTP/A VP 0 3//协议为RTP,剖面为A VP//参考rtp-parameters.txti=* (media title媒体称呼) //c=* (connection information –如已经包含在会话级描述则为可选)b=* (bandwidth information) //同ck=* (encryption key) //会话级为摸认值,同ca=* (zero or more media attribute lines) //两种形式:(也同c)(见后说明)//a=<attribute>如:// a=recvonly//a=<attribute>:<value>注:v,o,s,t,m为必须的,其他项为可选。
ts 类动态静态方法在TypeScript (TS) 中,类是面向对象编程的基本概念之一。
类中的方法可以被实例对象调用,也可以通过类本身调用。
其中,动态方法是指绑定在实例对象上的方法,而静态方法是指绑定在类本身上的方法。
本文将详细介绍TS中的类动态静态方法,并以示例的方式来说明其用法和特点。
二、动态方法1. 动态方法的定义和调用在TS中,动态方法是指绑定在类的原型(prototype)上的方法,并且可以通过实例对象来调用。
它的定义方式与普通函数类似,但需要在类中声明和绑定。
举例来说,有一个名为"Person"的类,其中有一个动态方法"sayHello",代码如下:class Person {sayHello() {console.log("Hello!");let person = new Person();person.sayHello();在上述代码中,我们先定义了一个Person类,然后在该类中声明并定义了一个动态方法`sayHello`。
接着,我们实例化了一个person对象,并通过`person.sayHello()`调用了这个动态方法。
2. 动态方法的特点动态方法具有以下特点:- 动态方法绑定在类的原型上,因此每个实例对象都共享同一个动态方法。
- 动态方法可以通过实例对象调用,因为每个实例对象都可以访问到类的原型。
- 动态方法内部可以使用this关键字来获得当前实例对象的引用。
举例来说,如果我们有多个Person对象,它们都可以调用sayHello方法,并共享同一个sayHello方法的实现。
let person1 = new Person();let person2 = new Person();person1.sayHello(); // 输出:Hello!person2.sayHello(); // 输出:Hello!在上述代码中,尽管person1和person2是由同一个Person类实例化出来的,但它们都可以独立地调用sayHello方法,并输出相同的结果。
C++在面向对象编程中,存在着静态绑定和动态绑定的定义,本节即是主要讲述这两点区分。
我是在一个类的继承体系中分析的,因此下面所说的对象一般就是指一个类的实例。
首先我们需要明确几个名词定义:
静态类型:对象在声明时采用的类型,在编译期既已确定;
动态类型:通常是指一个指针或引用目前所指对象的类型,是在运行期决定的;
静态绑定:绑定的是静态类型,所对应的函数或属性依赖于对象的静态类型,发生在编译期;
动态绑定:绑定的是动态类型,所对应的函数或属性依赖于对象的动态类型,发生在运行期;
从上面的定义也可以看出,非虚函数一般都是静态绑定,而虚函数都是动态绑定(如此才可实现多态性)。
先看代码和运行结果:
1 class A
2 {
3 public:
4 /*virtual*/ void func(){ std::cout << "A::func()\n"; }
5 };
6 class B : public A
7 {
8 public:
9 void func(){ std::cout << "B::func()\n"; }
10 };
11 class C : public A
12 {
13 public:
14 void func(){ std::cout << "C::func()\n"; }
15 };
下面逐步分析测试代码及结果,
1 C* pc = new C(); //pc的静态类型是它声明的类型C*,动态类型也是C*;
2 B* pb = new B(); //pb的静态类型和动态类型也都是B*;
3 A* pa = pc; //pa的静态类型是它声明的类型A*,动态类型是pa所指向的对象pc的类型C*;
4 pa = pb; //pa的动态类型可以更改,现在它的动态类型是B*,但其静态类型仍是声明时候的A*;
5 C *pnull = NULL; //pnull的静态类型是它声明的类型C*,没有动态类型,因为它指向了NULL;
如果明白上面代码的意思,请继续,
1 pa->func(); //A::func() pa的静态类型永远都是A*,不管其指向的是哪个子类,都是直接调用A::func();
2 pc->func(); //C::func() pc的动、静态类型都是C*,因此调用C::func();
3 pnull->func(); //C::func() 不用奇怪为什么空指针也可以调用函数,因为这在编译期就确定了,和指针空
不空没关系;
如果注释掉类C中的func函数定义,其他不变,即
1 class C : public A
2 {
3 };
4
5 pa->func(); //A::func() 理由同上;
6 pc->func(); //A::func() pc在类C中找不到func的定义,因此到其基类中寻找;
7 pnull->func(); //A::func() 原因也解释过了;
如果为A中的void func()函数添加virtual特性,其他不变,即
1 class A
2 {
3 public:
4 virtual void func(){ std::cout << "A::func()\n"; }
5 };
6
7 pa->func(); //B::func() 因为有了virtual虚函数特性,pa的动态类型指向B*,因此先在B中查找,
找到后直接调用;
8 pc->func(); //C::func() pc的动、静态类型都是C*,因此也是先在C中查找;
9 pnull->func(); //空指针异常,因为是func是virtual函数,因此对func的调用只能等到运行期才能确定,
然后才发现pnull是空指针;
分析:
在上面的例子中,
1. 如果基类A中的func不是virtual函数,那么不论pa、pb、pc指向哪个子类对象,对func的调用都是在定义pa、pb、pc
时的静态类型决定,早已在编译期确定了。
同样的空指针也能够直接调用no-virtual函数而不报错(这也说明一定要做空指针检查啊!),因此静态绑定不能实现多态;
2. 如果func是虚函数,那所有的调用都要等到运行时根据其指向对象的类型才能确定,比起静态绑定自然是要有性能损失的,
但是却能实现多态特性;
本文代码里都是针对指针的情况来分析的,但是对于引用的情况同样适用。
至此总结一下静态绑定和动态绑定的区别:
1. 静态绑定发生在编译期,动态绑定发生在运行期;
2. 对象的动态类型可以更改,但是静态类型无法更改;
3. 要想实现动态,必须使用动态绑定;
4. 在继承体系中只有虚函数使用的是动态绑定,其他的全部是静态绑定;
建议:
绝对不要重新定义继承而来的非虚(non-virtual)函数(《Effective C++ 第三版》条款36),因为这样导致函数调用由对象声
明时的静态类型确定了,而和对象本身脱离了关系,没有多态,也这将给程序留下不可预知的隐患和莫名其妙的BUG;
另外,在动态绑定也即在virtual函数中,要注意默认参数的使用。当缺省参数和virtual函数一起使用的时候一定要谨慎,不然
出了问题怕是很难排查。
看下面的代码:
1 class E
2 {
3 public:
4 virtual void func(int i = 0)
5 {
6 std::cout << "E::func()\t"<< i <<"\n";
7 }
8 };
9 class F : public E
10 {
11 public:
12 virtual void func(int i = 1)
13 {
14 std::cout << "F::func()\t" << i <<"\n";
15 }
16 };
17
18 void test2()
19 {
20 F* pf = new F();
21 E* pe = pf;
22 pf->func(); //F::func() 1 正常,就该如此;
23 pe->func(); //F::func() 0 哇哦,这是什么情况,调用了子类的函数,却使用了基类中参数的默认值!
24 }
为什么会有这种情况,请看《Effective C++ 第三版》 条款37。
这里只给出建议:
绝对不要重新定义一个继承而来的virtual函数的缺省参数值,因为缺省参数值都是静态绑定(为了执行效率),而virtual函数
却是动态绑定。