多态

C++虚函数表解析

匿名 (未验证) 提交于 2019-12-03 00:34:01
C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,这是一种泛型技术。所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议。 关于虚函数的使用方法,我在这里不做过多的阐述。大家可以看看相关的C++的书籍。在这篇文章中,我只想从虚函数的实现机制上面为大家 一个清晰的剖析。 当然,相同的文章在网上也出现过一些了,但我总感觉这些文章不是很容易阅读,大段大段的代码,没有图片,没有详细的说明,没有比较,没有举一反三。不利于学习和阅读,所以这是我想写下这篇文章的原因。也希望大家多给我提意见。 言归正传,让我们一起进入虚函数的世界。 虚函数表 对C++ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。简称为V-Table。 在这个表中,主是要一个类的虚函数的地址表,这张表解决了继承、覆盖的问题,保证其容真实反应实际的函数。这样,在有虚函数的类的实例中这个表被分配在了 这个实例的内存中,所以,当我们用父类的指针来操作一个子类的时候,这张虚函数表就显得由为重要了,它就像一个地图一样

软件构造笔记 3.4 Object-Oriented Programming (OOP)

匿名 (未验证) 提交于 2019-12-03 00:34:01
类变量和类方法与类相关联,并且每个类都会出现一次。使用它们不需要创建对象。实例方法和变量会在每个类的实例中出现一次。 静态方法不与任何特定的类实例关联,而实例方法(不带 static 关键字声明)必须在特定对象上调用。 1. 接口(interface): Java 的接口是一种用于设计和表达 ADT 的有用语言机制,其实现方式是实现该接口的类。接口之间可以继承,一个类也可以实现多个接口,一个接口也可以有多个实现。ADT由Interface和class定义和实现。其中接口用于确定ADT规约,类用于实现ADT。 打破了抽象边界,接口定义中没有包含 constructor ,也无法保证所有实现类中都包含了同样名字的 constructor 。故而,客户端需要知道该接口的某个具体实现类的名字 接口的优点:接口仅仅指定了客户端的合同;抽象数据类型的多个不同表示可以共同存在于同一个程序中,与实现接口的不同类相同。 多种实现的原因:由不同的表现能选择最适合您使用的实施方案;由不同的行为能选择你想要的实现;通常,性能和行为都有所不同。 2. 封装和信息隐藏 区分精心设计的模块和不好的模块的唯一最重要的因素是其隐藏内部数据和其他模块的其他实施细节的程度 设计良好的代码隐藏了所有实现细节,将 API 与实现完全分离,模块只通过 API 进行通信,彼此的内在运作没有联系。 信息隐藏的优势

虚函数与多态学习总结

匿名 (未验证) 提交于 2019-12-03 00:34:01
#include<iostream> using namespace std ; class Base { public : Base(char xx) { x = xx; } void who() { cout <<"Base class: " << x << "\n" ; } protected: char x; } ; class First_d : public Base { public : First_d(char xx, char yy):Base(xx) { y = yy; } void who() { cout <<"First derived class: "<< x << ", " << y<< "\n" ; } protected: char y; } ; class Second_d : public First_d { public : Second_d( char xx, char yy, char zz ) : First_d( xx, yy ) { z = zz; } void who() { cout <<"Second derived class: "<< x << ", " << y<< ", " << z << "\n" ; } protected: char z; } ; int main() { Base B_obj( 'A' ) ;

多态-成员变量访问

匿名 (未验证) 提交于 2019-12-03 00:32:02
成员变量 编译看左边(父类),运行看左边(父类) 成员方法 编译看左边(父类),运行看右边(子类)。动态绑定 静态方法 编译看左边(父类),运行看左边(父类)。 (静态和类相关,算不上重写,所以,访问还是左边的) 只有非静态的成员方法,编译看左边,运行看右边 class Demo2_Polymorphic { public static void main(String[] args) { /*Father f = new Son(); //父类引用指向子类对象 System.out.println(f.num); Son s = new Son(); System.out.println(s.num);*/ Father f = new Son(); //f.print(); f.method(); //相当于是Father.method() } } /* 成员变量 编译看左边(父类),运行看左边(父类) 成员方法 编译看左边(父类),运行看右边(子类)。动态绑定 静态方法 编译看左边(父类),运行看左边(父类)。 (静态和类相关,算不上重写,所以,访问还是左边的) 只有非静态的成员方法,编译看左边,运行看右边 */ class Father { int num = 10; public void print() { System.out.println("father"); }

C# 多态

匿名 (未验证) 提交于 2019-12-03 00:32:02
说完了继承,说多态。 所谓多态,即为多样。很显然这个多态/多样不是生物学中的那个名词。不过还是可以往这上面靠靠。 在讲多态之前,让我们思考一下代码: class NameList { public NameList() => Console.WriteLine( " 这个是NameList的构造函数 " ); public NameList( string Name) => Console.WriteLine($ " 这个是NameList的重载构造函数,输入的参数是{Name} " ); ~NameList() => Debug.WriteLine( " 释放NameList " ); public string Name { get ; set ; } public void ID() => Console.WriteLine($ " 我的id是{Name} " ); public void Show<T>(T type) where T : NameList => Console.WriteLine(type.GetType().FullName); } class A : NameList { public A() : base () => Console.WriteLine( " 这是A类的初始化,也就是构造函数 " ); public A( string Name) :

第五次实验:类的多态性

匿名 (未验证) 提交于 2019-12-03 00:29:01
(一)类的多态性练习 类的继承发生在多个类之间,而类的多态只发生在同一个类上。在一个类中,可以定义多个同名的方法,只要确定它们的参数个数和类型不同。这种现象称为类的多态。 多态使程序简洁,为程序员带来很大便利。在OOP 中,当程序要实现多个相近的功能时,就给相应的方法起一个共同的名字,用不同的参数代表不同的功能。这样,在使用方法时不论传递什么参数,只要能被程序识别就可以得到确定的结果。 类的多态性体现在方法的重载(overload)上,包括成员方法和构造方法的重载。 方法的重载是指对同名方法的不同使用方式。 class IntSort { public String sort (int a, int b) { if (a>b) return a+" "+b; else return b+" "+a; } int swap; if (a<b) { swap=a; a=b; b=swap; } if (a<c) { swap=a; a=c; c=swap; } if (b<c) { swap=b; b=c; c=swap; } return a+" "+b+" "+c; } } public class KY5_1 { int a=30, b=12, c=40; IntSort s=new IntSort(); System.out.println("两个数的排序结果:"+s.sort

抽象类和接口的区别与应用场景

匿名 (未验证) 提交于 2019-12-03 00:27:02
接口和抽象类有什么区别 在应用场景下,选择使用接口和抽象类的依据是什么? 一、抽象类和接口在语法上的异同: 1、相同点 都不能被实例化 第一点. 接口是抽象类的变体,接口比抽象类更加抽象,接口中所有的方法都是抽象的。 第二点. 每个类只能继承一个抽象类,但是可以实现多个接口 第三点.抽象类中不一定都是抽象方法,抽象的而抽象类可以实现部分方法。但是接口中方法必须为public修饰的、抽象的不能实现具体的法。 第四点. 接口中基本数据类型为static 而抽象类不是的。 二、应用场景 应用都是基于规则的应用,也就是基于语法的应用,我们可以根据语法上的异同点来总结抽象类和接口的应用场景 相同点没有什么可说的,我们从不同点下手。 1、第一个重要的不同点就是, 抽象类中不一定都是抽象的方法,也可以有具体实现的方法,这样就可以把大家公用的方法提升到抽象类中,然后具体的方法可以留给子类 自己实现(此处经典的应用,模板方法设计模式)。所以抽象类可以更好的实现代码的复用 2、另一个重要的不同就是类可以实现多个接口。 接口和抽象类的概念不一样。这个可以理解为接口是对动作的抽象,抽象类是对根源的抽象(即对本质的抽象与其他类的本质不同)。 抽象类表示的是,这个对象是什么。接口表示的是,这个对象能做什么。比如,男人,女人,这两个类(如果是类的话……),他们的抽象 类是人。说明,他们都是人。人可以吃东西

面向对象的三大基本特性,五大基本原则

匿名 (未验证) 提交于 2019-12-03 00:27:02
转自: https://www.jianshu.com/p/50999d81eeb5 透切理解面向对象三大基本特性是理解面向对象五大基本原则的基础. 三大特性是:封装,继承,多态 特征图 封装 封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。 封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。 继承 面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。 通过继承创建的新类称为“子类”或“派生类”。 被继承的类称为“基类”、“父类”或“超类”。 继承的过程,就是从一般到特殊的过程。 要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。 在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。 继承概念的实现方式有三类:实现继承、接口继承和可视继承。 实现继承是指使用基类的属性和方法而无需额外编码的能力; 接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力; ![Uploading 面向对象的三大基本特性图.png_922595.gif . . .]

小朋友学C++(12):多态

匿名 (未验证) 提交于 2019-12-03 00:26:01
(一) 先编写函数: #include <iostream> using namespace std; class Shape { protected : int width, height; public : Shape ( int a = 0 , int b = 0 ) { width = a; height = b; } int area() { cout << "Parent class area :" <<endl; return 0 ; } }; class Rectangle: public Shape { public : Rectangle ( int a = 0 , int b = 0 ) { } int area () { cout << "Rectangle class area :" <<endl; return (width * height); } }; class Triangle: public Shape { public : Triangle ( int a= 0 , int b= 0 ) : Shape(a, b) { } int area () { cout << "Triangle class area :" <<endl; return (width * height / 2 ); } }; int main( ) { Shape

在继承多态中关于this的使用

匿名 (未验证) 提交于 2019-12-03 00:22:01
通过this调用method和filed的区别 在继承多态中: 1、对于方法的覆盖,new的谁就调谁,这就是多态。 2、对于成员变量的覆盖,this在哪个类就指向哪个类的成员变量,没有多态。 public class ThisTest { @override public void Test(){ Fu f = new Zi(); System.out.println(f.num);//这里定义的是父类,而成员变量没有多态,所以即使你new的子类,依然指向父类的成员变量。 System.out.println(f.fun1());//不解释了,就是多态。 f.show(); } } class Fu { public String num = "父类成员变量"; public void show() { System.out.println(this.num);//因为成员变量没有多态,所以this指向当前类对象的成员变量。 System.out.println(this.fun1());//因为方法有多态,所以this指向new对象的方法。 System.out.println(this);//打印的是子类对象 } public String fun1() { System.out.println(this.num);//因为成员变量没有多态,所以this指向当前类对象的成员变量