导航:首页 > 源码编译 > 什么实现编译时的多态性

什么实现编译时的多态性

发布时间:2024-06-18 19:22:28

Ⅰ C++缂栫▼涓澶氭佹х殑瀹炵幇链哄埗鍒板簳鏄浠涔埚憖锛

钬滀竴涓瀵瑰栨帴鍙o纴澶氢釜鍐呭湪瀹炵幇钬

琛ュ厖锛氱紪绋嬫槸缂栧啓绋嫔簭镄勪腑鏂囩亩绉帮纴灏辨槸璁╄$畻链轰负瑙e喅镆愪釜闂棰樿屼娇鐢ㄦ煇绉岖▼搴忚捐¤瑷缂栧啓绋嫔簭浠g爜锛屽苟链缁埚缑鍒扮浉搴旂粨鏋灭殑杩囩▼銆

涓轰简浣胯$畻链鸿兘澶熺悊瑙d汉镄勬剰锲撅纴浜虹被灏卞繀椤昏佸皢闇瑙e喅镄勯梾棰樼殑镐濊矾銆佹柟娉曘佸拰镓嬫豹鐭ヨ繜娈甸氲繃璁$畻链鸿兘澶熺悊瑙g殑褰㈠纺锻婅瘔璁$畻链猴纴浣垮缑璁$畻链鸿兘澶熸牴鎹浜虹殑鎸囦护涓姝ヤ竴姝ュ幓宸ヤ綔锛屽畬鎴愭煇绉岖壒瀹氩汹𨱒庣殑浠诲姟銆傝繖绉崭汉鍜岃$畻链轰箣闂翠氦娴佺殑杩囩▼灏辩寷绌楁槸缂栫▼銆

缂栫▼锛氲捐″叿澶囬昏緫娴佸姩浣灭敤镄勪竴绉嵝滃彲鎺т綋绯烩濄愭敞锛氱紪绋嬩笉涓瀹氭槸阍埚硅$畻链虹▼搴忚岃█镄勶纴阍埚瑰叿澶囬昏緫璁$畻锷涚殑浣撶郴锛岄兘鍙浠ョ畻缂栫▼銆

渚嫔瓙锛气憼姣斿傜紪鍐欎竴娈典唬镰佺▼搴忊憽缂栧啓涓涓鎺у埗璁惧囦綋绯汇

Ⅱ 什么叫做多态性 在C++中是如何实现多态的

C++中的多态(虽然多态不是C++所特有的,但是C++中的多态确实是很特殊的)分为静多态和动多态(也就是静态绑定和动态绑定两种现象),静动的区别主要在于这种绑定发生在编译期还是运行期,发生在编译期的是静态绑定,也就是静多态;发生在运行期的则是动态绑定,也就是动多态。

静多态可以通过模板和函数重载来实现(之所说C++中的多态主要还是因为模板这个东西),下面举两个例子:
1)函数模板
template <typename T>
T max(const T& lsh, const T& rhs)
{
return (lsh > rhs) ? lsh : rhs;
}
返回两个任意类型对象的最大值(对象),前提是该类型能够使用>运算符进行比较,并且返回值是bool类型。
使用:
int a = 3; int b = 4;
cout << max(a, b) << endl;
float c = 2.4; float d = 1.2;
cout << max(c, d) << endl;
输出结果为:
4
2.4
这种绑定发生在编译期,这是由于模板的实例化是发生在编译期的,即在编译时编译器发现你调用max(a, b)时就自动生成一个函数
int max(const int& lsh, const int& rhs)
{
return (lsh > rhs) ? lsh : rhs;
}
即将所有的T替换成int;
当你调用max(c, d)时就自动生成一个函数
float max(const float& lsh, const float& rhs)
{
return (lsh > rhs) ? lsh : rhs;
}
之所以说开始的函数定义是函数模板,就是因为他就像个模子似的,你可以用铝作为原料也可以用石膏或者铜。
2)函数重载:
int max (int a, int b)
{
return (a > b) ? a : b;
}
int max (int a, int b, int c)
{
return max(max(a, b), c);
}
两个函数名称一样,参数类型或个数不完全相同,返回值一样(这个不重要)。
使用:
int a = 3, b = 4, c = 5;
cout << max(a, b) << endl;
cout << max(a, b, c) << endl;
输出结果为:
4
5
确定函数的过程也发生在编译器,当你使用max(a, b),编译器发现只有两个参数,那么就调用只有两个参数的函数版本,当使用max(a, b, c)时,编译器则使用有3个参数的版本。
通过上面的两个例子,你还可以使用更为方便的模板函数重载:
template <typename T>
T max(const T& lsh, const T& rhs)
{
return (lsh > rhs) ? lsh : rhs;
}

template <typename T>
T max(const T& a, const T& b, const T& c)
{
return max(max(a, b), c);
}
使用
float a = 3.6, b = 1.2, c = 7.8;
cout << max(a, b, c) << endl;
输出:
7.8
通过参数个数和类型,编译器自动生成和调用对应得函数版本!

动多态则是通过继承、虚函数(virtual)、指针来实现。
class A {
public:
virtual void func() const {
coust << “A::func()” << endl;
}
}

class B : public A {
public:
virtual void func() const {
coust << “B::func()” << endl;
}
}
使用:
A a* = B();
a->func();
输出:
B::func()
编译期是不调用任何函数的,编译器编译到a->func()时只是检查有没有语法问题,经过检查没有。编译器并不知道调用的是A版本的func()还是B版本的func(),由于a是一个指向B对象的指针,所以a只知道它指向的是一个A类型(或者能转换成A类型)的对象。通常集成体系就说明了(由于是公有继承)B是一种A。在运行期,a要调用a所指向对象的func()函数,就对它指向的对象下达调用func()的命令,结果a所指向的是一个B对象,这个对象就调用了自己版本(B版)的func()函数,所以输出时B::func()

总结:
在编译期决定你应该调用哪个函数的行为是静态绑定(static-binding),这种现象就是静多态。
在运行期决定应该调用哪中类型对象的函数的行为是动态绑定(dynamic-binding),这种现象就是动多态!

注:由于这是我花了有限的时间总结的,语言应用能力比较差,还有比如类模板(静多态和动多态组合的情况)都没有说,最近比较忙,请见谅!

如果还不是很懂,我建议你看C++Primer 4th Edition,讲的比较清晰,但是比较零散!

Ⅲ 1. 编译时的多态性与运行时的多态性有什么区别,他们的实现方法有什么不同

多态从实现的角度可以划为两类:编译时多态和运行时多态。

编译时的多态性:就是在程序编译的时候,也就是生成解决方案的时候就决定要实现什么操作。

运行时的多态性:就是指直到系统运行时,才根据实际情况决定实现何种操作。

1、多态实现形式不同:

编译时的多态是通过静态连编来实现的;运行时的多态是用动态连编来实现的。

2、多态性通过方式不同:

编译时的多态性主要是通过函数重载和运算符重载来实现的;运行时的多态性主要是通过虚函数来实现的。

(3)什么实现编译时的多态性扩展阅读:

静态多态性又称编译时的多态性。静态多态性的函数调用速度快、效率高但缺乏灵活性,在程序运行前就应决定执行的函数和方法。

动态多态性的特点是:不在编译时确定调用的是哪个函数,而是在程序运行过程中才动态地确定操作所针对的对象。又称运行时的多态性。动态多态性是通过虚函数(virtual function)实现的。

Ⅳ c++涓镄勮櫄鍑芥暟链変粈涔堜綔鐢锛

绫荤殑涓変釜閲嶈佺壒寰侊细灏佽呫佺户镓裤佸氭佹с
鍏朵腑澶氭佹у氨鏄阃氲繃鍑芥暟閲嶈浇锛堣繍绠楃﹂吨杞藉疄璐ㄤ笂涔熸槸鍑芥暟閲嶈浇锛夊拰铏氩嚱鏁版潵瀹炵幇镄勚
铏氩嚱鏁扮殑浣灭敤锛氩湪锘虹被鐢╲irtual澹版槑鎴愬憳鍑芥暟涓鸿櫄鍑芥暟锛屽湪娲剧敓绫讳腑閲嶆柊瀹氩瓭鍦嗗苟涔夎ュ嚱鏁帮纴灏卞彲浠ラ氲繃锘虹被鎸囬拡鎴栧紩鐢ㄦ潵璁块梾锘虹被鍜屾淳鐢熺被涓镄勫悓钖嶅嚱鏁般
铏氩嚱鏁板疄鐜板氭佹э细钖屼竴绫绘棌涓涓嶅悓绫荤殑瀵硅薄锛屽瑰悓涓鍑芥暟璋幂敤锅氩嚭涓嶅悓镄勫搷搴斻
澶氭佹у叾瀹炲氨鏄涓涓鎺ュ彛锛屽氱嶆柟娉曪纴鍒嗕负闱欐佸氭佹у拰锷ㄦ佸氭佹э纴鍑芥暟閲嶈浇灞炰簬闱栾厰闂规佸氭佹э纴鍦ㄧ▼搴忕紪璇戞椂灏卞彲纭瀹氲皟鐢ㄥ摢涓鍑芥暟锛屽叾杩囩▼绉颁负闱欐佸叧镵旀垨镞╂湡鍏宠仈锛岄润镐佸氩阀杩规佹у张绉扮紪璇戞椂澶氭佹э绂铏氩嚱鏁板睘浜庡姩镐佸氭佹э纴鍦ㄧ▼搴忚繍琛岃繃绋嬩腑镓嶅姩镐佸湴纭瀹氭墍璋幂敤镄勬槸闾d釜瀵硅薄镄勫嚱鏁帮纴鍏惰繃绋嬬О涓哄姩镐佸叧镵旀垨婊炲悗鍏宠仈锛屽姩镐佸氭佹у张绉拌繍琛屾椂澶氭佹с

Ⅳ C++支持的两种多态性分别是什么

静态联编支持的多态性称为编译时的多态性,也称静态多态性,它是通过函数重载和运算符重载实现的。
动态联编支持的多态性称为运行时的多态性,也称动态多态性,它是通过继承和虚函数实现的。

Ⅵ C++中多态是怎样实现的

多态是一种不同的对象以单独的方式作用于相同消息的能力,这个概念是从自然语言中引进的。例如,动词“关闭”应用到不同的事务上其意思是不同的。关门,关闭银行账号或关闭一个程序的窗口都是不同的行为;其实际的意义取决于该动作所作用的对象。 大多数面向对象语言的多态特性都仅以虚拟函数的形式来实现,但C++除了一般的虚拟函数形式之外,还多了两种静态的(即编译时的)多态机制: 2、模板:例如,当接受到相同的消息时,整型vector对象和串vector对象对消息反映是不同的,我们以关闭行为为例: vector < int > vi; vector < string > names; string name("VC知识库"); vi.push_back( 5 ); // 在 vector 尾部添加整型 names.push_back (name); // 添加串和添加整型体现差别的潜在的操作 静态的多态机制不会导致与虚拟函数相关的运行时开。此外,操作符重载和模板两者是通用算法最基本的东西,在STL中体现得尤为突出。 那么接下来我们说说以虚函数形式多态: 通常都有以重载、覆盖、隐藏来三中方式,三种方式的区别大家应该要很深入的了解,这里就不多说了。 许多开发人员往往将这种情况和C++的多态性搞混淆,下面我从两方面为大家解说: 1、 编译的角度 C++编译器在编译的时候,要确定每个对象调用的函数的地址,这称为早期绑定(early binding)。2、 内存模型的角度为了确定对象调用的函数的地址,就要使用迟绑定(late binding)技术。当编译器使用迟绑定时,就会在运行时再去确定对象的类型以及正确的调用函数。而要让编译器采用迟绑定,就要在基类中声明函数时使用virtual关键字(注意,这是必须的,很多开发人员就是因为没有使用虚函数而写出很多错误的例子),这样的函数我们称为虚函数。一旦某个函数在基类中声明为virtual,那么在所有的派生类中该函数都是virtual,而不需要再显式地声明为virtual。 那么如何定位虚表呢?编译器另外还为每个类的对象提供了一个虚表指针(即vptr),这个指针指向了对象所属类的虚表。在程序运行时,根据对象的类型去初始化vptr,从而让vptr正确的指向所属类的虚表,从而在调用虚函数时,就能够找到正确的函数。 正是由于每个对象调用的虚函数都是通过虚表指针来索引的,也就决定了虚表指针的正确初始化是非常重要的。换句话说,在虚表指针没有正确初始化之前,我们不能够去调用虚函数。那么虚表指针在什么时候,或者说在什么地方初始化呢? 答案是在构造函数中进行虚表的创建和虚表指针的初始化。还记得构造函数的调用顺序吗,在构造子类对象时,要先调用父类的构造函数,此时编译器只“看到了”父类,并不知道后面是否后还有继承者,它初始化父类对象的虚表指针,该虚表指针指向父类的虚表。当执行子类的构造函数时,子类对象的虚表指针被初始化,指向自身的虚表。 要注意:对于虚函数调用来说,每一个对象内部都有一个虚表指针,该虚表指针被初始化为本类的虚表。所以在程序中,不管你的对象类型如何转换,但该对象内部的虚表指针是固定的,所以呢,才能实现动态的对象函数调用,这就是C++多态性实现的原理。总结(基类有虚函数):1、 每一个类都有虚表。2、虚表可以继承,如果子类没有重写虚函数,那么子类虚表中仍然会有该函数的地址,只不过这个地址指向的是基类的虚函数实现。如果基类3个虚函数,那么基类的虚表中就有三项(虚函数地址),派生类也会有虚表,至少有三项,如果重写了相应的虚函数,那么虚表中的地址就会改变,指向自身的虚函数实现。如果派生类有自己的虚函数,那么虚表中就会添加该项。3、派生类的虚表中虚函数地址的排列顺序和基类的虚表中虚函数地址排列顺序相同。

Ⅶ 编译时的多态性和运行时的多态性在实现方法上有何不同

我不知道你哪本书上看到的,但是,只要不是后绑定就不能称为多态,前绑定只能称为代码重用,比如函数的重载、覆盖以及一般的类继承。
多态的关键特点就是:在运行时虚基类指针指向派生类对象地址,而将派生类对象地址赋值给基类指针,这就是所谓的后绑定,编译时绑定称为前绑定,因此多态另一个特点就是“动态“。换句话说,如果是后绑定,编译器事先是不知道在运行时指针将指向哪一种派生类的对象,因此基类指针必须是“虚“的,虚基类中不能有任何实现只有定义,此时虚基类的作用就是一个类接口,这样才能在编译时“模糊”掉类型匹配原则,基类的作用只是个约定,定义了函数调用格式,而只在运行时才确定指针具体指向哪一个对象。
而所谓编译时的多态性根本不存在,如果编译器能确定基类指针指向哪一个派生类对象地址,就不是多态,哪怕你采用重载覆盖或者继承,这些编译器已经可以预知的事情,一旦编译完成就固定了,运行时无法更改的,比如你不能在不重新编译的情况下增加一个重载,这就制约了程序运行时的灵活性以及可扩充性。而多态完全可以实现“热“更新,更多的是便于程序的可扩充性。你完全可以将派生类编译在DLL中,每当更新程序时,只要替换掉DLL而不用重新编译全部代码。

Ⅷ 编译时多态性使用什么获得!A重载函数B继承C虚函数D.B和C

函数重载和模板。就这题来说选A。
继承和虚函数对应的多态需要在运行的时候才能确定具体对象,所以不属于编译时多态。

函数重载是让一个函数名对应多个函数,编译器会根据调用时候的特征确定要调用的函数,不需要再运行时处理。
而模板是让一个一个类型模板或者函数模板对应多个类型或者函数,编译器根据对模板实例化是使用的参数生成具体的类和函数,也不是在运行时进行的。
另外注意模板变量不属于多态范畴。

阅读全文

与什么实现编译时的多态性相关的资料

热点内容
安卓os14怎么默认桌面 浏览:547
应用市场下载在哪个文件夹 浏览:893
安卓上的谷歌地图怎么用 浏览:181
安卓命令行打包 浏览:514
编程文字与数字教学视频 浏览:815
如何看手机号码注册哪些app 浏览:411
linux查看总内存 浏览:850
python进程间共享 浏览:436
js如何获取本地服务器地址 浏览:68
gfx什么时候支持安卓十一系统 浏览:939
压缩机90兆帕 浏览:928
程序员调侃语句 浏览:579
不是php函数的是 浏览:998
压缩文件好处 浏览:785
3d266期神童三胆计算法 浏览:189
通过爱思助手怎么下载app 浏览:323
vi命令将文件创在桌面上 浏览:924
程序员做竞价 浏览:698
江苏中小学编程纳入课程 浏览:732
单纯形法包括动态规划算法 浏览:951