首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

在c ++中进行子类化时为什么有时需要添加虚拟关键字来覆盖函数?

在C++中,子类化时有时需要添加虚拟关键字来覆盖函数,是因为使用虚拟函数可以实现动态多态。动态多态是指在运行时根据对象的实际类型来调用相应的函数,而不是在编译时根据指针或引用的类型来调用函数。

虚拟函数的作用是允许子类重写父类中的函数,并在运行时通过基类指针或引用调用子类中的函数。如果没有使用虚拟关键字,子类中的函数将隐藏父类中的同名函数,而不是重写它。这将导致在运行时调用的是父类中的函数,而不是子类中的函数,从而破坏了动态多态的机制。

因此,在C++中,如果需要在子类中重写父类中的函数,并且希望在运行时通过基类指针或引用调用子类中的函数,就需要在父类中的函数前添加虚拟关键字。这样,编译器就会为父类中的函数生成一个虚拟函数表,并在子类中的函数被调用时,通过查找虚拟函数表来确定实际调用的函数。

总之,在C++中,为了实现动态多态,需要在父类中的函数前添加虚拟关键字,并在子类中重写该函数。这样,在运行时通过基类指针或引用调用函数时,就会根据实际对象的类型来调用相应的函数。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

Java培训实战教程之Java基础知识精华部分(四)(五)

如果想要调用父类的属性值,需要使用一个关键字:super this:代表是本类类型的对象引用。 super:代表是子类所属的父类的内存空间引用。...当一个类的功能内容需要修改时,可以通过覆盖实现。 3:构造函数。 发现子类构造函数运行时,先运行了父类的构造函数为什么呢?...而super():是调用父类中空参数的构造函数为什么子类对象初始化时,都需要调用父类函数?(为什么要在子类构造函数的第一行加入这个super()?)...因为子类继承父类,会继承到父类的数据,所以必须要看父类是如何对自己的数据进行初始化的。 所以子类进行对象初始化时,先调用父类的构造函数,这就是子类的实例化过程。...如果子类构造函数中用this指定调用子类自己的构造函数,那么被调用的构造函数也一样会访问父类的构造函数

42930

万丈高楼平地起,爆肝21000字Java基础知识总结,收藏起来总有用得着的时候

而super():是调用父类中空参数的构造函数为什么子类对象初始化时,都需要调用父类函数?(为什么要在子类构造函数的第一行加入这个super()?)...因为子类继承父类,会继承到父类的数据,所以必须要看父类是如何对自己的数据进行初始化的。所以子类进行对象初始化时,先调用父类的构造函数,这就是子类的实例化过程。...4:只有通过子类继承抽象类并覆盖了抽象类的所有抽象方法后,该子类才可以实例化。否则,该子类还是一个抽象类。 抽象类的细节: 1:抽象类是否有构造函数?有,用于给子类对象进行初始化。...2,覆盖接口中的run方法(用于封装线程要运行的代码)。3,通过Thread类创建线程对象;4,将实现了Runnable接口的子类对象作为实际参数传递给Thread类的构造函数为什么要传递呢?...:** **创建对象的两种方式(其实就是对象进行实例化时的初始化方式):** 1,调用空参数的构造函数:使用了Class类的**newInstance()**方法。

47611
  • Java基础知识总结

    而super():是调用父类中空参数的构造函数为什么子类对象初始化时,都需要调用父类函数?(为什么要在子类构造函数的第一行加入这个super()?)...因为子类继承父类,会继承到父类的数据,所以必须要看父类是如何对自己的数据进行初始化的。所以子类进行对象初始化时,先调用父类的构造函数,这就是子类的实例化过程。...(静态只能覆盖静态,或者被静态覆盖) 继承的一个弊端:打破了封装性。对于一些类,或者类功能,是需要被继承,或者复写的。 这时如何解决问题呢?介绍一个关键字,final。...4:只有通过子类继承抽象类并覆盖了抽象类的所有抽象方法后,该子类才可以实例化。否则,该子类还是一个抽象类。 抽象类的细节: 1:抽象类是否有构造函数?有,用于给子类对象进行初始化。...: 创建对象的两种方式(其实就是对象进行实例化时的初始化方式): 1,调用空参数的构造函数:使用了Class类的newInstance()方法。

    1.3K31

    Java 小白成长记 · 第 6 篇「为什么说要慎用继承,优先使用组合」

    组合,新类 Cat 访问旧类 Animal 的属性需要通过内嵌的旧类对象调用,而对于继承来说,「新类(子类)可以直接调用旧类(父类)的公有属性」。UML 类图如下: ?...,这个同 this 关键字一样,「使用 super调用构造函数的语句必须是子类构造函数的第一条语句」。...如果超类没有无参构造函数, 并且子类的构造器又没有显式地调用超类的其他构造器,则 Java 编译器将报告错误。 ❞ 需要注意的是:「父类的构造函数总是先于子类的构造函数执行」。...正像有时需要将浮点型数值 float 转换成整型数值 int 一样,有时候也可能需要「将某个父类的对象引用转换成子类的对象引用,调用一些子类特有而父类没有的方法」。...,后续会详细讲解,这里大家只需要知道 add 用来向集合添加一个元素,addAll 用来向集合添加多个元素即可。

    89720

    「MoreThanJava」Day 5:面向对象进阶—继承详解

    其他成员将在其类定义添加子类。 视频观影 App 示例 Java 编程是通过创建类层次结构并从中实例化对象完成的。您可以扩展自己的类或扩展已经存在的类。...我们需要给 Movie 类添加新的 toString() 的使用方法: // 添加到 Movie 类 public String toString() { return "title:" +...特别是,如果父类方法是 public,子类方法必须也要声明为 public。 final 关键字 有时候,我们可能希望组织人们利用某个类定义子类。...然而,如果 getName 另外一个类覆盖,那么编译器就无法知道覆盖的代码将会做什么操作,因此也就不能对它进行内联处理了。...如果方法很短、被频繁调用而且确实没有被覆盖,那么即时编译器就会将这个方法进行内联处理。如果虚拟机加载了另外一个子类,而这个子类覆盖了一个内联方法,那么优化器将取消对这个方法的内联。

    51010

    Swift vs. Kotlin 漫谈系列之类与继承

    如果想要让某个类可以被继承,必须要现式的为该类添加 open 的关键字,该关键字提供了和 Java final 相反的功能。 Swift: ?,为什么要区分?...如果子类想要重写某个方法,必须用 override 关键字修饰该方法,否则会报错。被 override 修饰的函数默认也是开放的,如果不想它再被继承,需要 final 修饰该函数。...Swift: Swift 函数倒是不需要,不过也需要用 override 关键字修饰。...默认类的函数也是静态的,如果一个函数需要被重写,我们必须手动让他变成开放的,即在函数前面添加 open 关键字。...但是 f() 由 C 继承了两个实现,所以我们必须在 C 覆盖 f() 并且提供我们自己的实现消除歧义。

    3.6K40

    Java编程思想重点笔记(Java开发必看)

    只有非private方法才可以被覆盖,但是还需要密切注意覆盖private方法的现象,这时虽然编译器不会报错,但是也不会按照我们所期望的执行,即覆盖private方法对子类来说是一个新的方法而非重载方法...因此,子类,新方法名最好不要与基类的private方法采取同一名字(虽然没关系,但容易误解,以为能够覆盖基类的private方法)。 Java类属性域的访问操作都由编译器解析,因此不是多态的。...2. is-a关系和is-like-a关系 is-a关系属于纯继承,即只有基类已经建立的方法才可以子类中被覆盖,如下图所示: ?...有时基类的创建者会希望有某个特定成员,把对它的访问权限赋予派生类而不是所有类。这就需要protected完成这一工作。...有两种办法可以防止对象的敏感部分被序列化: 两者反序列化时的区别: - 对Serializable对象反序列化时,由于Serializable对象完全以它存储的二进制位为基础构造,因此并不会调用任何构造函数

    73430

    2.7w字!2021 最新版!Java基础面试题知识点总结!(上)

    有时,即使您不打算在计算机上进行任何 Java 开发,仍然需要安装 JDK。例如,如果要使用 JSP 部署 Web 应用程序,那么从技术上讲,您只是应用程序服务器运行 Java 程序。...但是,有时候可能需要在循环的过程,当发生了某种条件之后 ,提前终止循环,这就需要用到下面几个关键词: continue :指跳出当前的这一次循环,继续下一次循环。...如果我们自己添加了类的构造方法(无论是否有参),Java 就不会再添加默认的无参数的构造方法了,这时候,就不能直接 new 一个对象而不传递参数了,所以我们一直不知不觉地使用构造方法,这也是为什么我们创建对象的时候后面要加一个括号...transient 关键字的作用是:阻止实例那些用此关键字修饰的的变量序列化;当对象被反序列化时,被 transient 修饰的变量值不会被持久化和恢复。...有时,即使您不打算在计算机上进行任何 Java 开发,仍然需要安装 JDK。例如,如果要使用 JSP 部署 Web 应用程序,那么从技术上讲,您只是应用程序服务器运行 Java 程序。

    79500

    java面试(基础-1)

    有时,即使您不打算在计算机上进行任何Java开发,仍然需要安装JDK。例如,如果要使用JSP部署Web应用程序,那么从技术上讲,您只是应用程序服务器运行Java程序。那你为什么需要JDK呢?... Java 定义一个不做事且没有参数的构造方法的作用 Java 程序执行子类的构造方法之前,如果没有用 super() 调用父类特定的构造方法,则会调用父类“没有参数的构造方法”。...因此,如果父类只定义了有参数的构造方法,而在子类的构造方法又没有用 super() 调用父类特定的构造方法,则编译时将发生错误,因为 Java 程序父类找不到没有参数的构造方法可供执行。...33 Java序列化如果有些字段不想进行序列化,怎么办? 对于不想进行序列化的变量,使用transient关键字修饰。...transient关键字的作用是:阻止实例那些用此关键字修饰的的变量序列化;当对象被反序列化时,被transient修饰的变量值不会被持久化和恢复。

    58360

    virtual

    函数的使用就是为了方便多态的使用,常常需要在基类定义虚函数,然后对基类进行继承,再对基类的虚函数进行重载。...覆盖函数前必须加关键字virtual,重载和virtual没有任何关系。 关于C++的隐藏规则 如果派生类的函数与基类的函数同名,但是参数不同。...此时,基类的函数被隐藏(注意别与覆盖混淆)。 纯虚函数 C++语言为我们提供了一种语法结构,通过它可以指明,一个虚拟函数只是提供了一个可被子类型改写的接口。...如果我们子类定义了从父类继承的虚函数,对于父类来说情况是不变的,对于子类来说它的虚函数表与之前的虚函数表是一样的,但是此时子类定义了自己的(从父类那继承的)相应函数,所以它的虚函数表当中关于这个函数的指针就会覆盖掉原有的指向父类函数的指针的值...函数覆盖和隐藏 父类和子类出现同名函数称为隐藏 父类对象.函数名() 调用父类的函数 子类对象.函数名() 调用子类函数 子类对象.父类名::函数名() 子类调用从父类继承函数 父类和子类出现同名虚函数称为覆盖

    65150

    关于Java基础的34个问题

    有时,即使您不打算在计算机上进行任何Java开发,仍然需要安装JDK。例如,如果要使用JSP部署Web应用程序,那么从技术上讲,您只是应用程序服务器运行Java程序。那你为什么需要JDK呢?... Java 定义一个不做事且没有参数的构造方法的作用  Java 程序执行子类的构造方法之前,如果没有用 super() 调用父类特定的构造方法,则会调用父类“没有参数的构造方法”。...因此,如果父类只定义了有参数的构造方法,而在子类的构造方法又没有用 super() 调用父类特定的构造方法,则编译时将发生错误,因为 Java 程序父类找不到没有参数的构造方法可供执行。...早期的Java实现版本,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升(现在的Java版本已经不需要使用final方法进行这些优化了)。...transient关键字的作用是:阻止实例那些用此关键字修饰的的变量序列化;当对象被反序列化时,被transient修饰的变量值不会被持久化和恢复。

    1.7K50

    关于Java基础你不得不会的34个问题

    有时,即使您不打算在计算机上进行任何Java开发,仍然需要安装JDK。例如,如果要使用JSP部署Web应用程序,那么从技术上讲,您只是应用程序服务器运行Java程序。那你为什么需要JDK呢?... Java 定义一个不做事且没有参数的构造方法的作用  Java 程序执行子类的构造方法之前,如果没有用 super() 调用父类特定的构造方法,则会调用父类“没有参数的构造方法”。...因此,如果父类只定义了有参数的构造方法,而在子类的构造方法又没有用 super() 调用父类特定的构造方法,则编译时将发生错误,因为 Java 程序父类找不到没有参数的构造方法可供执行。...早期的Java实现版本,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升(现在的Java版本已经不需要使用final方法进行这些优化了)。...transient关键字的作用是:阻止实例那些用此关键字修饰的的变量序列化;当对象被反序列化时,被transient修饰的变量值不会被持久化和恢复。

    94620

    【附答案】关于Java基础你不得不会的34个问题

    有时,即使您不打算在计算机上进行任何Java开发,仍然需要安装JDK。例如,如果要使用JSP部署Web应用程序,那么从技术上讲,您只是应用程序服务器运行Java程序。那你为什么需要JDK呢?... Java 定义一个不做事且没有参数的构造方法的作用  Java 程序执行子类的构造方法之前,如果没有用 super() 调用父类特定的构造方法,则会调用父类“没有参数的构造方法”。...因此,如果父类只定义了有参数的构造方法,而在子类的构造方法又没有用 super() 调用父类特定的构造方法,则编译时将发生错误,因为 Java 程序父类找不到没有参数的构造方法可供执行。...早期的Java实现版本,会将final方法转为内嵌调用。但是如果方法过于庞大,可能看不到内嵌调用带来的任何性能提升(现在的Java版本已经不需要使用final方法进行这些优化了)。...transient关键字的作用是:阻止实例那些用此关键字修饰的的变量序列化;当对象被反序列化时,被transient修饰的变量值不会被持久化和恢复。

    47730

    2.7w字!2021 最新版!Java基础面试题知识点总结!(上)

    有时,即使您不打算在计算机上进行任何 Java 开发,仍然需要安装 JDK。例如,如果要使用 JSP 部署 Web 应用程序,那么从技术上讲,您只是应用程序服务器运行 Java 程序。...那你为什么需要 JDK 呢?因为应用程序服务器会将 JSP 转换为 Java servlet,并且需要使用 JDK 编译 servlet。 为什么说 Java 语言“编译与解释并存”?...但是,有时候可能需要在循环的过程,当发生了某种条件之后 ,提前终止循环,这就需要用到下面几个关键词: continue :指跳出当前的这一次循环,继续下一次循环。...如果我们自己添加了类的构造方法(无论是否有参),Java 就不会再添加默认的无参数的构造方法了,这时候,就不能直接 new 一个对象而不传递参数了,所以我们一直不知不觉地使用构造方法,这也是为什么我们创建对象的时候后面要加一个括号...transient 关键字的作用是:阻止实例那些用此关键字修饰的的变量序列化;当对象被反序列化时,被 transient 修饰的变量值不会被持久化和恢复。

    45110

    java基础知识总结(绝对经典)

    当一个类的功能内容需要修改时,可以通过覆盖实现。 3:构造函数。 发现子类构造函数运行时,先运行了父类的构造函数为什么呢?...而super():是调用父类中空参数的构造函数为什么子类对象初始化时,都需要调用父类函数?(为什么要在子类构造函数的第一行加入这个super()?)...因为子类继承父类,会继承到父类的数据,所以必须要看父类是如何对自己的数据进行初始化的。所以子类进行对象初始化时,先调用父类的构造函数,这就是子类的实例化过程。...(静态只能覆盖静态,或者被静态覆盖) 继承的一个弊端:打破了封装性。对于一些类,或者类功能,是需要被继承,或者复写的。 这时如何解决问题呢?介绍一个关键字,final:最终。...4:只有通过子类继承抽象类并覆盖了抽象类的所有抽象方法后,该子类才可以实例化。否则,该子类还是一个抽象类。 抽象类的细节: 1:抽象类是否有构造函数?有,用于给子类对象进行初始化。

    65000

    2.7w字!Java基础面试题知识点总结!(2021 最新版)

    有时,即使您不打算在计算机上进行任何 Java 开发,仍然需要安装 JDK。例如,如果要使用 JSP 部署 Web 应用程序,那么从技术上讲,您只是应用程序服务器运行 Java 程序。...那你为什么需要 JDK 呢?因为应用程序服务器会将 JSP 转换为 Java servlet,并且需要使用 JDK 编译 servlet。 为什么说 Java 语言“编译与解释并存”?...但是,有时候可能需要在循环的过程,当发生了某种条件之后 ,提前终止循环,这就需要用到下面几个关键词: continue :指跳出当前的这一次循环,继续下一次循环。...综上:重载就是同一个类多个同名方法根据不同的传参执行不同的逻辑处理。 重写 重写发生在运行期,是子类对父类的允许访问的方法的实现过程进行重新编写。...transient 关键字的作用是:阻止实例那些用此关键字修饰的的变量序列化;当对象被反序列化时,被 transient 修饰的变量值不会被持久化和恢复。

    54120

    C++ 虚拟继承

    1.为什么要引入虚拟继承 虚拟继承是多重继承特有的概念。虚拟基类是为解决多重继承而出现的。如:类D继承自类B1、B2,而类B1、B2都继 承自类A,因此类D两次出现类A的变量和函数。...,所以也往往被忽视,这也主要是因为C++,多重继承是不推荐的,也并不常用,而一旦离开了多重继承,虚拟继承就完全失去了存在的必要因为这样只会降低效率和占用更多的空间。...为什么需要虚继承? 由于C++支持多重继承,那么在这种情况下会出现重复的基类这种情况,也就是说可能出现将一个类两次作为基类的可能性。比如像下面的情况 ?...4.2“覆盖”是指派生类函数覆盖基类函数,特征是: (1)不同的范围(分别位于派生类与基类); (2)函数名字相同; (3)参数相同; (4)基类函数必须有virtual 关键字。...也就是说子类把父类的私有变量也继承下来了,但是却无法访问,对于我这种菜鸟来说一下子没法转个弯,后来看看资料焕然大悟,子类虽然无法直接访问父类的私有变量,但是子类继承的父类的函数却可以访问,不然的话如果只继承函数而不继承变量

    2.3K80

    06 Java 的继承

    声明方法时最后添加@Override注解,@Override注解不是方法覆盖必须的,但添加 @Override 注解有两个好处: 提高程序的可读性。...覆盖的应用 当子类需要父类的功能,而功能主体子类有自己特有内容时,可以复写父类的方法,这样也沿袭了父类的功能 构造方法类继承的作用 构造方法不能继承.由于子类对象要对来自父类的成员进行初始化,因此...,创建子类对象时除了执行子类的构造方法外,还需要调用父类的构造方法.具体遵循如下原则: 当子类未定义构造方法时,创建对象时将无条件地调用父类的空构造方法,会默认第一条添加super(); 对于父类的含参数构造方法...,子类可以自己构造方法中使用关键字 super 调用它, 但 super 调用语句必须是子类构造方法的第一个可执行语句; 子类自己定义构造方法如果没有用 super 明确调用父类的构造方法,则在创建对象时...当有多个重名函数的时候,决定要调用哪个函数的过程,首先是按照参数类型进行匹配的,换句话说,寻找在所有重载版本中最匹配的,然后才看变量的动态类型,进行动态绑定。

    53020

    C++:44---关键字virtual、override、final

    如果类方法类外进行定义,那么override不能加 不一定强制要求子类声明这个关键字,但是建议使用(见下面的五) 这是C++11标准填入的 override设计的最初原因: 有些情况下,我们的父类定义了一个虚函数...编译器会将派生类中新定义的这个函数与基类中原有的虚函数相互独立,这时,派生类的函数没有覆盖掉基类的虚函数版本,虽然程序没有出错,但是却违反了最初的原则 因此C++11标准添加了一个override关键字放在派生类的虚函数后...void f4()override; //错误,B没有名为f4的函数 }; 五、禁止覆盖(final关键字) 如果我们定义的一个虚函数不想被派生类覆盖(重写),那么可以函数之后添加一个...方法是通过域运算符实现 通常,只有成员函数(或友元)的代码才需要使用作用域运算符来回避虚函数的机制 什么时候需要用到这种回避虚函数的机制: 通常,基类定义的虚函数要完成继承层次中所有的类都要完成的共同的任务...,而各个派生类函数各自添加自己的功能。

    4K31

    C++【多态】

    ),而构成虚表又需要函数,即 virtual 修饰的函数,除此之外还需要使用虚表指针进行函数定位、调用 2.1、构成多态的两个必要条件 必要条件 virtual 修饰后形成的虚函数,与其他类的虚函数形成...虚函数的作用是目标函数(想要构成多态的函数)之间构成 重写(覆盖),一旦构成了 重写(覆盖),那么子类对象实现此虚函数时,会 继承父类的虚函数接口(返回值、函数名、参数列表),然后覆盖子类对应的虚函数处...、实际形态未确定的函数,使用 virtual 修饰后,就是告诉编译器:标记此函数,调用时要触发 覆盖 行为,同时虚表指针需要找到正确的函数进行调用 注意: 除了类的成员函数外,普通函数不能添加 virtual...同样的,假设不是父类指针或引用进行调用,不会构成多态,也不会发生重写(覆盖)行为 2.3、final 与 override C++11 ,新增了两个多态相关的关键字:final、override...但实际情况是 子类中新增的虚函数默认添加至第一张虚表 通过 PrintVFTable 函数打印虚表进行验证 因此此时有两张虚表,所以需要分别打印 第一张虚表简单,直接取地址+类型强转,如法炮制即可

    13730

    扫码

    添加站长 进交流群

    领取专属 10元无门槛券

    手把手带您无忧上云

    扫码加入开发者社群

    相关资讯

    热门标签

    活动推荐

      运营活动

      活动名称
      广告关闭
      领券