多态

c++学习笔记:多态

僤鯓⒐⒋嵵緔 提交于 2020-03-30 17:21:18
1.多态:通常是指对于同一个消息、同一种调用,在不同的场合,不同的情况下,执行不同的行为--->重载便是简单的多态 ------->指同一个操作作用于不同的对象就会产生不同的响应; 多态性分为静态多态性和动态多态性   其中函数重载和运算符重载属于静态多态性, 虚函数属于动态多态性---->C++是依靠虚函数来实现动态多态的。 2.C++编译器根据传递给函数的参数和函数名决定具体要使用哪一个函数,称为联编:   1)在编译过程中进行的联编叫静态联编(static binding)或早期联编(early binding)。   2)在程序运行时完成,动态联编”(dynamic binding)也叫晚期联编(late binding)---->C++通过虚函数来实现动态联编 3.虚函数:vitual   1.与基类的虚函数有相同的参数个数;   2.与基类的虚函数有相同的参数类型;   3.与基类的虚函数有相同的返回类型。   注意点:1. 基类的成员函数定义为虚函数,那么,它在所有派生类中也保持为虚函数;即使在派生类中省略了virtual关键字,也仍然是虚函数。       2.构造函数不可为虚函数--->一旦为虚函数相当于重新,在构造子类时无法找到基类构造函数从而无法构造对象。       ( 1. 根据继承的性质,构造函数执行顺序是: A() B() 2. 根据虚函数的性质

C++基础学习笔记

ぐ巨炮叔叔 提交于 2020-03-30 17:19:57
  虚函数:虚函数是动态绑定的基础。虚函数必须是非静态的成员函数,虚函数经过派生后在类族中就可以实现运行过程中的多态。   根据类型兼容原则,可以使用派生类的对象代替基类对象。如果用基类类型的指针指向派生类对象,就可以通过这个指针来访问该对象, 问题是访问到的只是从基类中继承来的同名函数。 解决办法:若需要通过基类指针指向派生类对象,并且访问某个与基类同名的成员,首先在基类中将该同名函数声明为 虚函数。 如此,通过基类类型的指针,就可使属于不同派生类的不同对象产生的不同的行为,从而实现运行过程的多态。    虚函数在类的定义中使用 virtual 关键字来限定成员函数。注:虚函数声明只能出现在类定义中的函数原型声明中,而不能在成员函数实现的时候。   运行时多态需满足三个条件:1、类之间满足 类型兼容原则 。2、要声明 虚函数 。3、 由成员函数来调用或通过指针、引用来访问虚函数 。 #include <iostream> using namespace std; class B0 { public: virtual void display(){cout << "B0::display()" <<endl;} }; class B1:public B0 { public: void display(){cout << "B1::display()" <<endl;} };

难免的尴尬:代码依赖

只愿长相守 提交于 2020-03-30 16:47:33
相关文章连接 动力之源:代码中的泵 高屋建瓴:梳理编程约定 编程之基础:数据类型(一) 编程之基础:数据类型(二) 可复用代码:组件的来龙去脉 重中之重:委托与事件 物以类聚:对象也有生命 难免的尴尬:代码依赖 12.1 从面向对象开始 12.1.1 对象基础:封装 12.1.2 对象扩展:继承 12.1.3 对象行为:多态 12.2 不可避免的代码依赖 12.2.1 依赖存在的原因 12.2.2 耦合与内聚 12.2.3 依赖造成的尴尬 12.3 降低代码依赖 12.3.1 认识抽象与具体 12.3.2 再看“依赖倒置原则” 12.3.3 依赖注入 12.4 框架中的“代码依赖” 12.4.1 控制转换 12.4.2 依赖注入对框架的意义 12.5 本章回顾 12.6 本章思考 在浩瀚的代码世界中,有着无数的对象,跟人和人之间有社交关系一样,对象跟对象之间也避免不了接触,所谓接触,就是指一个对象要使用到另外对象的属性、方法等成员。现实生活中一个人的社交关系复杂可能并不是什么不好的事情,然而对于代码中的对象而言,复杂的"社交关系"往往是不提倡的,因为对象之间的关联性越大,意味着代码改动一处,影响的范围就会越大,而这完全不利于系统重构和后期维护。所以在现代软件开发过程中,我们应该遵循"尽量降低代码依赖"的原则,所谓尽量,就已经说明代码依赖不可避免。 有时候一味地追求"降低代码依赖

C++类内存分布

房东的猫 提交于 2020-03-30 02:39:27
转自:http://www.cnblogs.com/jerry19880126/p/3616999.html C++类内存分布 书上类继承相关章节到这里就结束了,这里不妨说下C++内存分布结构,我们来看看编译器是怎么处理类成员内存分布的,特别是在继承、虚函数存在的情况下。 工欲善其事,必先利其器,我们先用好Visual Studio工具,像下面这样一步一步来: 先选择左侧的C/C++->命令行,然后在其他选项这里写上/d1 reportAllClassLayout,它可以看到所有相关类的内存布局,如果写上/d1 reportSingleClassLayoutXXX(XXX为类名),则只会打出指定类XXX的内存布局。近期的VS版本都支持这样配置。 下面可以定义一个类,像下面这样: 1 class Base 2 { 3 int a; 4 int b; 5 public: 6 void CommonFunction(); 7 }; 然后编译一下,可以看到输出框里面有这样的排布: 这里不想花精力在内存对齐因素上,所以成员变量都设为int型。 从这里可以看到普通类的排布方式,成员变量依据声明的顺序进行排列(类内偏移为0开始),成员函数不占内存空间。 再看下继承,往后面添加如下代码: 1 class DerivedClass: public Base 2 { 3 int c; 4 public

C++ 虚函数表与多态 —— 关键字 override 的用法

主宰稳场 提交于 2020-03-30 01:51:13
override 仅能用于虚函数,他属于C++新特性,是重写覆盖的意思,他的存在仅仅是为了提高代码的可阅读性: 作用: 1. 提示程序的阅读者,这个函数是重写父类的功能。 2. 防止程序员在重写父类的函数时,把函数名写错。 如下代码: 1 #include <iostream> 2 3 using namespace std; 4 5 class Class_1 6 { 7 virtual void func() 8 { 9 cout << "AAA" << endl; 10 } 11 12 }; 13 14 class Class_2 :public Class_1 15 { 16 void func() override //方法后加 override,可以方便程序员阅读代码,知道这方法是重写的,不用回去找 17 { 18 cout << "BBB" << endl; 19 } 20 }; 再比如: 1 #include <iostream> 2 3 using namespace std; 4 5 class Class_1 6 { 7 virtual void func() 8 { 9 cout << "AAA" << endl; 10 } 11 12 }; 13 14 class Class_2 :public Class_1 15 { 16 void func_1()

C++ 虚函数表与多态 —— 关键字 final 的用法

≯℡__Kan透↙ 提交于 2020-03-30 01:44:21
final 字面上最终、最后、不可改变的意思,final 这个关键字在 Jave PHP C++中都有用到,其作用也基本一致。 C++中的 final 是C++11新增,他可以用来修饰类,让类无法被继承;或用来修饰类的虚函数,让虚函数在子类中不能被重写。 final 只能修饰 类 与 虚函数,无法修饰普通成员函数。 一、 在类的继承关系中 final 的用法,让类无法被继承: 1 #include <iostream> 2 3 using namespace std; 4 5 class Class_1 final //可以再一开始就修饰 final 6 { 7 8 }; 9 10 class Class_2 final :public Class_1 //报错:不能将 final 类用作基类 11 { 12 13 }; 14 15 class Class_3 :public Class_2    //报错:不能将 final 类用作基类 16 { 17 18 }; 二、 虚函数禁止重写的 final 的方法,让虚函数在子类中不能被重写:   这种情况,可以继承,可以使用,只是不能够重写。 1 #include <iostream> 2 3 using namespace std; 4 5 class Class_1 6 { 7 virtual void func() final

c# 多态性

天涯浪子 提交于 2020-03-28 22:55:44
首先理解一下什么叫多态。同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果,这就是 多态性 。 多态性 通过派生类覆写基类中的虚函数型方法来实现。 多态性 分为两种,一种是编译时的 多态性 ,一种是运行时的 多态性 。 编译时的 多态性 :编译时的 多态性 是通过重载来实现的。对于非虚的成员来说,系统在编译时,根据传递的参数、返回的类型等信息决定实现何种操作。 运行时的 多态性 :运行时的 多态性 就是指直到系统运行时,才根据实际情况决定实现何种操作。C#中运行时的 多态性 是通过覆写虚成员实现。 下面我们来分别说明一下多态中涉及到的四个概念:重载,覆写,虚方法和抽象方法。 重载和覆写的区别: 重载 类中定义的方法的不同版本 public int Calculate(int x, int y) public double Calculate(double x, double y) 特点(两必须一可以) 方法名必须相同 参数列表必须不相同 返回值类型可以不相同 覆写 子类中为满足自己的需要来重复定义某个方法的不同实现。 通过使用override关键字来实现覆写。 只有虚方法和抽象方法才能被覆写。 要求(三相同) 相同的方法名称 相同的参数列表 相同的返回值类型 最后再来介绍一下虚方法和抽象方法 虚方法: 声明使用virtual关键字。 调用虚方法

深入理解面向对象 -- 基于 JavaScript 实现

痴心易碎 提交于 2020-03-27 08:43:04
我们在学习编程时,避免不了会接触一个概念,叫: 面向对象编程(Object-oriented programming,缩写:oop) (不是搞对象那个对象哈),其实我们的编程方式,不止有面向对象,还有 面向过程编程 、 面向流编程 、 面向函数编程 、 面向接口编程 等。作为一名一直混迹在前端的小菜鸟,今天就来跟大家深入的探讨一下 JavaScript面向对象 。作为程序员,我们多多少少都会接触自己擅长语言之外的编程语言,比如我作为一名前端,同时我还会 Java ,从这两个语言本身出发的话,我们会发现这两种语言的 面向对象 存在着一丝丝的不同,到底哪里不同呢?我们今天就拿这两种语言对比着来,拿具体的实例看一下,到底什么叫 面向对象编程 。 现在很多文章都会讲 面向对象三大特性 、 面向对象七原则 、 设计模式 等概念,今天这篇文章不准备讲这些概念,从实例出发,理解 面向对象 是什么,如何做 面向对象 程序设计。 我们在深入探讨 面向对象 之前,我们先来复习一下 面向过程编程 ,这里可能有人会问了,不是讲 面向对象 吗?为什么还要讲 面向过程 呢?主要是因为, 面向过程编程 是软件思想中的鼻祖。 面向过程编程 还是很好理解的,因为它是一种以 过程 作为中心的编程思想,其中 过程 的含义就是 完成一件事情的步骤 。 面向过程 其实是一种 机械的思想 ,它就像流水线一样

Objective-C--- 多态 、 协议

点点圈 提交于 2020-03-27 08:11:38
1 编写交通工具程序 1.1 问题 本案例需要创建一个TRTransportation类,类中有一个方法叫print的方法,该方法默认输出 “显示交通工具信息”,这个类作为父类,派生出三个子类TRTaxi的士类、TRBus巴士类和TRBike 自行车类。TRTaxi的士类覆盖了父类的print方法,改成自己的输出,"交通工具为的士";TRBus巴士类覆盖了父类的print方法,改成自己的输出,"交通工具为巴士";TRBike 自行车类覆盖了父类的print方法,改成自己的输出,"交通工具为单车"。 在主程序中,创建三个交通工具,使用多态输出交通工具信息。 1.2 步骤 实现此案例需要按照如下步骤进行。 步骤一:定义TRTransportation类 首先,在Day04工程中新添加TRTransportation.h文件,用于定义新的类TRTransportation。 代码如下所示: # import <Foundation /Foundation .h > @ interface TRTRansportation : NSObject -( void )print ; @end 在上述代码中,为TRTransportation类添加一个方法print,用于输出信息“显示交通工具信息”到控制台。 然后,在类TRTransportation的实现部分

Objective-C 封装 继承 多态

回眸只為那壹抹淺笑 提交于 2020-03-27 06:09:37
封装 #import <Foundation/Foundation.h> @interface Person : NSObject { //@public int _age; } - (void) setAge : (int) age; - (int) age; @end @implementation Person - (void) setAge : (int) age { if(age <= 0) { age = 1; } _age = age; } - (int) age { return _age; } @end int main() { Person *p = [Person new]; //p->age = 10; //NSLog(@"年龄是: %i", p->age); [p setAge : 0]; NSLog(@"年龄是: %i", [p age]); return 0; } /** 注意我的命名规范 **/ //封装的好处: 代码的安全性高 继承和组合 #import <Foundation/Foundation.h> @interface AClass : NSObject { int _age; int _height; } @end @implementation AClass @end /** 继承 **/ @interface BClass :