多态

C++ 多态(迟绑定)原理

江枫思渺然 提交于 2019-12-03 22:03:58
今天看到一篇帖子关于虚函数的问题,原以为自己已经对c++虚函数,多态了解的不错了,但是,还是发现有一些模糊点,所以,又回头重新总结了一番。 有了不小的收获,下面,就和大家一起来分享一下,也希望对一些朋友起到一定的帮助。 首先先梳理一下概念,以前似乎对概念不是很重视,其实不然,真正对一个东西的定义了解了很透,才能去深入挖掘这个东西的内涵。 好,首先,什么是绑定?( what`s the definition of binding? ) c++编程思想上有说到: Connecting a function call to a function body is called binding.(将函数体和函数调用关联起来,就叫绑定) 然后,那么什么是早绑定?(Early binding) When binding is performed before the program is run (by the compiler and linker), it' s called early binding 在程序运行之前(也就是编译和链接时),执行的绑定是早绑定。 然后,什么是迟绑定?(late binding) late binding, which means the binding occurs at runtime, based on the type of the object.

C++中的动态绑定即多态的意义和原理

你说的曾经没有我的故事 提交于 2019-12-03 22:03:34
[size=medium] 首先梳理一下概念: 1.什么是绑定?(What's the definition of binding?) 将函数体和函数调用关联起来,就叫绑定! 2.什么是早绑定? 早绑定是指在程序运行之前,即编译和链接是执行的绑定就是早绑定! 3.什么事迟绑定? 迟绑定就是指发生在运行时,基于不同类型的对象。对函数调用不同的函数体是发生的绑定。当一种语言要实现迟绑定是,必须有某种机制去确定对象的具体类型,然后调用适当的成员函数! 其次我们来看一个小例子: class Animal{ public: virtual void sleep() { cout<<"Animall sleep!"<<endl; } void breath() { cout<<"Animall breath!"<<endl; } }; class Fish:public Animal { public: void sleep() { cout<<"Fish sleep!"<<endl; } void breath() { cout<<"Fish breath!"<<endl; } }; int main() { cout << "Hello world!" << endl; Fish f; Animal* a=&f; a->breath(); a->sleep(); return 0; }

c++ 虚函数实现多态的原理

自作多情 提交于 2019-12-03 22:02:57
前面的文章说过了c++如何实现多态,最主要的就是使用虚函数,另一种方法就是RTTI,这里我们不做说明了。前面说过编译器是这样实现晚绑定的:编译器对每一个含有virtual函数的类创建一个虚函数表vtable,其实vtable就是一个函数指针数组,vtable中存放该类的类型信息和这个类所有的虚函数地址,而且在这个类中,编译器会隐含的设置一个指向这个虚函数表的虚拟指针vptr。每个类vptr的设定和重置是通过类的构造函数、析构函数和拷贝复制运算符自动完成。vtable中的type_info object就是支持RTTI的,一般放在vtable的第一个位置。看下面的一段含有继承关系的代码 class Base { public: Base(); virtual ~Base() {}; virtual void test() { std::cout << "Base::test" << std::endl; } private: int b_i; }; class Derived : public Base { public: virtual void test() { std::cout << "Derived::test" << std::endl; } private: int d_i; }; 他们的对象在内存布局大概形式如图所示 若是没有虚函数时就不需要中间的vtable间接查找

C++多态

南笙酒味 提交于 2019-12-03 21:59:29
C++多态 概念 C++中实现多态的条件 重写、同名隐藏与重载 多态实现原理 多态实现过程: 扩展 概念 多种形态,在完成某个行为时,当不同的对象去完成时会产生不同的形态。多态又分为动态多态和静态多态。 静态多态 (静态绑定,早绑定):编译器在编译时确定调用哪个函数(体现:函数重载、模板)。 动态多态 (动态绑定,晚绑定):编译时无法确定具体调用哪个函数,只有在代码运行时才知道具体应该调用哪个函数(体现:虚函数+重写)。 C++中实现多态的条件 1.在继承体系中,基类中必须要有 虚函数 ,派生类必须对基类进行 重写 。 2.必须 通过基类的指针或引用 去调用虚函数。 上面两个条件缺一不可。 但是也有两个例外: 协变 和 析构函数 。 协变 :返回值类型不同。基类虚函数返回基类的指针或引用,派生类虚函数返回派生类的指针或引用。基类虚函数也可以返回另一个继承体系基类的指针或引用,其派生类虚函数返回与基类返回的指针或引用相同继承体系的派生类指针或引用。 析构函数 :只要基类中的析构函数被virtual关键字修饰,如果其派生类的显式提供了自己的析构函数,则形成重写。 重写、同名隐藏与重载 重写 :派生类重写基类的虚函数,必须保证派生类虚函数与基类函数的原型(返回值类型、函数名字、参数列表)完全相同。 重载 :只要参数列表(参数个数,参数顺序,参数类型)不同,就构成重载,与返回值无关。

C++多态:深入虚函数,理解晚绑定

可紊 提交于 2019-12-03 21:59:11
 C++的多态特性是通过晚绑定实现的。晚绑定(late binding),指的是编译器或解释器程序在运行前,不知道对象的类型。使用晚绑定,无需检查对象的类型,只需要检查对象是否支持特性和方法即可。  在C++中,晚绑定通常发生在使用 virtual 声明成员函数时。此时,C++创建一个虚函数表,当某个函数被调用时需要从这个表中查找该函数的实际位置。通常,晚绑定也叫做动态函数分派(dynamic dispatch)。  考虑如下的代码: #include<iostream> using namespace std ; class D { public : int num; D( int i = 0 ) { num = i; } virtual void print() { cout << "I'm a D. my num=" << num << endl; }; }; class E : public D { public : E( int i = 0 ) { num = i; } void print() { cout << "I'm a E. my num=" << num << endl; } void ppp() { int ttt = 1 ; } }; int main() { void (D::*i)() = &D::print; E* e = new E( 1 ); e

C++多态技术

孤街浪徒 提交于 2019-12-03 15:57:23
C++多态技术 多态(polymorphism)一词最初来源于希腊语polumorphos,含义是具有多种形式或形态的情形。在程序设计领域,一个广泛认可的定义是 “一种将不同的特殊行为和单个泛化记号相关联的能力”。和纯粹的面向对象程序设计语言不同,C++中的多态有着更广泛的含义。除了常见的通过类继承和虚函 数机制生效于运行期的动态多态(dynamic polymorphism)外,模板也允许将不同的特殊行为和单个泛化记号相关联,由于这种关联处理于编译期而非运行期,因此被称为静态多态 (static polymorphism)。 事实上,带变量的宏和函数重载机制也允许将不同的特殊行为和单个泛化记号相关联。然而,习惯上我们并不将它们展现出来的行为称为多态(或静态多态)。今 天,当我们谈及多态时,如果没有明确所指,默认就是动态多态,而静态多态则是指基于模板的多态。不过,在这篇以C++各种多态技术为主题的文章中,我们首 先还是回顾一下C++社群争论已久的另一种“多态”:函数多态(function polymorphism),以及更不常提的“宏多态(macro polymorphism)”。 函数多态 也就是我们常说的函数重载(function overloading)。基于不同的参数列表,同一个函数名字可以指向不同的函数定义: // overload_poly.cpp #include

C++ 多态详解及常见面试题

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-03 13:34:23
       今天,讲一讲多态:         多态就是 不同对象对同一行为会有不同的状态 。 (举例 : 学生和成人都去买票时,学生会打折,成人不会)        实现多态有两个条件: 一是 虚函数 重写 , 重写就是用来设置不同状态的                  二是对象调用虚函数时必须是 指针或者引用                       什么是虚函数?什么是重写?         虚函数是带有 virtual 关键字的 成员函数          子类有个和父类 完全相同 (函数名,形参,返回值都相同,协变和析构函数除外) 的 虚函数 ,就称子类虚函数重写父类虚函数                  多态的原理?         多态是用 虚函数表 实现的。        有虚函数的类都会生成一个虚函数表, 这个表在 编译时 生成。        虚函数表是一个 存储虚函数地址的 数组 ,以NULL结尾。        如果要生成子类虚表,就要经过三个步骤:第一步,将父类虚表内容 拷贝 到子类虚表上;                          第二步,将子类 重写的虚函数覆盖掉 表中父类的虚函数;                          第三步,如果子类有 新增加 的虚函数,按 声明次序加到最后        多态如何调用?        

python学习-66 面向对象3 - 多态

怎甘沉沦 提交于 2019-12-03 11:04:54
                 多态 1.什么是多态 由不同的类实例化得到的对象,调用同一个方法,执行的逻辑不同。 举例: class H2O: def __init__(self,type,tem): self.type = type self.tem = tem def turn_ice(self): if self.tem < 0: print('%s,冻成为冰了' % self.tem) elif self.tem >0: print('%s,液化成水了' % self.tem) class Ice(H2O): pass class Water(H2O): pass i1 = Ice('冰',-20) w1 = Water('水',20) def func(obj): obj.turn_ice() func(i1) func(w1) 运行结果: -20,冻成为冰了 20,液化成水了 Process finished with exit code 0 来源: https://www.cnblogs.com/liujinjing521/p/11792534.html

关于多态的概念以及用途的简单理解(通俗易懂)

亡梦爱人 提交于 2019-12-03 10:21:21
多态的定义和一些理解: (1)派生类对象的地址可以赋值给基类指针。对于通过基类指针调用基类和派生类中都有的同名、同参数表的虚函数的语句,编译时并不确定要执行的是基类还是派生类的虚函数;而当程序运行到该语句时,如果基类指针指向的是一个基类对象,则基类的虚函数被调用,如果基类指针指向的是一个派生类对象,则派生类的虚函数被调用。这种机制就叫作“多态(polymorphism)”。 (2)所谓“虚函数”,就是在声明时前面加了 virtual 关键字的成员函数。virtual 关键字只在类定义中的成员函数声明处使用,不能在类外部写成员函数体时使用。静态成员函数不能是虚函数。 (3)包含虚函数的类称为“多态类”。 (4)多态可以简单地理解为同一条函数调用语句能调用不同的函数;或者说,对不同对象发送同一消息,使得不同对象有各自不同的行为。 (5)多态在面向对象的程序设计语言中如此重要,以至于有类和对象的概念,但是不支持多态的语言,只能被称作“基于对象的程序设计语言”,而不能被称为“面向对象的程序设计语言”。例如,Visual Basic 就是“基于对象的程序设计语言”。 一个小例子: 执行结果: 当我们没有使用多态,父类指针只能够访问子类的成员,而不能访问成员函数,当我们在父类的成员函数前面加一个virtual,使其成为了一个虚函数过后,父类的指针就可以访问子类的成员函数了。 总得来说

作业七

左心房为你撑大大i 提交于 2019-12-03 10:12:40
20182302 2019-2020-1 《数据结构与面向对象程序设计》第7周学习总结 教材学习内容总结 SOLID原则:SRP单一职责原则,OCP开放封闭原则,LSP likov替代原则,ISP接口分离原则,DIP依赖导致原则。(仍未完全理解掌握) 继承封装多态的相关含义。 如何通过接口实现多态,如何利用继承实现多态(实际操作不能完全自己打出)后绑定相关概念 教材学习中的问题和解决过程 问题1: 对四种输出方法无法分离 问题1解决方案:通过仔细阅读理解老师所给代码为两种输入,其下又各有两种shuc 问题2:对字符流,字节流理解存在困难 问题2解决方案:通过交流询问和查阅课本找到相关概念区别。:字符流使用了缓冲区,而字节流没有使用缓冲区。在字节流中输出数据主要是使用OutputStream完成,输入使的是InputStream,在字符流中输出主要是使用Writer类完成,输入流主要使用Reader类完成。(这四个都是抽象类)。 代码调试中的问题和解决过程 问题1:try-catch不理解如何使用 问题1解决方案:查阅后得知try与catch的不同作用。 问题2: 在java中输入字符遇到吃回车问题 问题2解决方案:百度后得知通过将nextline改为next可以解决,nextline常发生吃回车问题 问题3:append的作用不知. 问题3解决方案