首页
学习
活动
专区
圈层
工具
发布

基类派生类多态虚函数?

当我们使用指针或引用调用虚函数时,该调用将被动态绑定。...根据引用或指针所绑定的对象类型不同,该调用可能执行基类的版本,也可能执行某个派生类的版木,基类通过在其成员函数的声明语句之前加上关键字virtual使得该函数执行动态绑定。...成员函数如果没被声明为虚函数,则其解析过程发生在编译时而非运行时。就会按照实际情况调用。 派生类可以继承定义在基类中的成员,但是派生类的成员函数不一定有权访问从基类继承而来的成员。...派生类必须通过使用类派生列表(clss erivatin list)明确指出它是从哪个(哪些)基类继承而来的。...如果派生类没有覆盖其基类中的某个虚函数,则该虚函数的行为类似于其他的普通成员,派生类会直接继承其在基类中的版本,派生类可以在它覆盖的函数前使用virtual关键字,但不是非得这么做(可有可无)。

45420

c++继承 基类 派生类 虚函数

1.调用基类的构造函数 2.调用派生类的构造函数 派生类的析构可想而知: 1.调用派生类的析构函数 2.调用基类的析构函数  虚函数  如下程序:  class Base { public:     Base...基类中含有虚函数,那么基类布局中存在一个虚函数指针,指向虚函数表;且其派生类中与其同名同参的函数不需要加virtual也是虚函数。...此时基类和派生类的布局如下:     vfptr的指针大小为4(32位机器)。因此基类字节数为8,派生类为12。...pb是一个指针类型,它的类型只和定义点有关,因此打印出来pb的类型为class Base类型;而pb是一个自定义类型,动态获取类型时,先通过指针pb解引用找到派生类对象,通过vfptr找到vftable...首先通过指针所指向的对象找到vfptr,再找到vftable,获取到Show函数的入口地址,此时 &Derive::Show中存放的是派生类的虚函数入口地址,因此调用的是派生类中的Show()函数。

1.4K20
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    菱形继承问题及解决方法—虚继承与虚基类(C++)

    菱形继承 菱形继承的概念 两个派生类继承同一个基类,又有某个类同时继承着这两个派生类 菱形继承典型案例 这种继承带来的问题主要有两方面: 羊和驼都继承了动物的类成员,当羊驼想要使用时,会产生二义性...二是通过虚继承的方式,使羊驼仅继承一份数据。...m_Age,通过限定作用域的方式无法彻底解决这个问题,这个时候就要使用虚继承 虚继承与虚基类 具体实现为在羊类和驼类的继承前加上virtual关键词,Animal类称为虚基类 代码如下: #include...可以看出羊类和驼类中的数据只是一个虚基类指针,并未继承具体的数据,这个虚基类指针指向各自的虚基类表,而虚基类表中存在一个偏移量,通过这个偏移量再加上首地址可以找到基类中的数据,所以实际上羊驼只继承了一份数据...(也就是基类中的那份)。

    1.4K40

    C++虚基类

    如果一个派生类有多个直接基类,而这些直接基类又有一个共同的基类,则在最终的派生类中会保留该间接共同基类数据成员的多份同名成员。C++提供虚基类的方法,使得在继承间接共同基类时只保留一份成员。...现在,将类A声明为虚基类,方法如下: class A//声明基类A {…}; class B :virtual public A//声明类B是类A的公用派生类,A是B的虚基类 {…}; class...C :virtual public A//声明类C是类A的公用派生类,A是C的虚基类 {…}; 注意: 虚基类并不是在声明基类时声明的,而是在声明派生类时,指定继承方式时声明的。...因为一个基类可以在生成一个派生类时作为虚基类,而在生成另一个派生类时不作为虚基类。...可以看到A的构造函数被调用了两遍!下面我们把A改成虚基类再看看结果。

    1.2K20

    派生类对基类中虚函数和非虚函数的继承效果

    ,所以他只认哪个指针指向自己,这里是Animal指针指向,所以他就调用Animal里面的,普通函数是父类为子类提供的“强制实现”,也就是只要是父类指针调用普通函数,那就是父类的普通函数 而虚函数的作用,...主要是为了让父类指针可以调用子类的函数,这种是在运行时才决定调用哪个函数 1、虚函数:   C++的虚函数主要作用是“运行时多态”,父类中提供虚函数的实现,为子类提供默认的函数实现。...子类可以重写父类的虚函数实现子类的特殊化。 2、纯虚函数:   C++中包含纯虚函数的类,被称为是“抽象类”。抽象类不能使用new出对象,只有实现了这个纯虚函数的子类才能new出对象。   ...3、普通函数:   普通函数是静态编译的,没有运行时多态,只会根据指针或引用的“字面值”类对象,调用自己的普通函数。   普通函数是父类为子类提供的“强制实现”。   ...因此,在继承关系中,子类不应该重写父类的普通函数,因为函数的调用至于类对象的字面值有关。 参考链接

    74510

    【Example】C++ 虚基类与虚继承 (菱形继承问题)

    虚基类并不是“绝对的”,而是“相对的”:虚基类在它自身声明、定义的时候无需任何修饰,只是在子类继承时进行 virtual 修饰。...同时,在虚继承机制当中,虚基类是由最终的派生类进行初始化的,本身达成了一种 “间接继承” 的关系。 也就意味着最终的派生类在构造函数初始化中,要在初始化表中调用虚基类的构造函数进行初始化。...这样,就保证了虚基类不会被二次初始化。...public: Expert() {}; ~Expert() {}; }; class Blu : public Byte, public Expert { public: // 调用虚基类构造函数...public 公有成员 :基类、派生类、友元、外部都可以访问 protected 保护成员: 基类、派生类、友元可以访问 private 私有成员 :基类、友元可以访问 继承方式 基类 public

    1.2K30

    接口,抽象类,抽象方法,虚方法简单总结

    为了确保实现接口的类都有接口中描述的功能,所以子类必须去实现接口中定义的方法(可以是抽象方法或者是虚方法)。...(修改为抽象类) //public abstract string GetName(); //定义成虚方法 //public virtual string GetName()...抽象方法只能定义在抽象类中。因为抽象类是对一类事物的抽象,所以它可以有字段。抽象类跟接口一样不能被实例化。原因我想是这样的,他们都具有未实现的方法,如果能实例化了,那方法怎么调用呢。...虚方法: 当父类中的某个功能(方法)子类可能不一样的时候,可以在父类中把这个方法定义成虚方法。因为只是可能不一样,所以父类中的虚方法有具体实现(方法体),子类可以去重写也可以不重写。...接口中的方法,抽象方法,虚方法都不能被private修饰,因为他们都是方便子类设计的,如果是私有的,那就没意思了。

    68210

    C++虚拟继承与虚基类

    多重继承使得派生类与基类的关系变得更为复杂,其中一个容易出现问题是某个基类沿着不同的路径被派生类继承(即形成所谓“菱形继承”),从而导致一个派生类对象中存在同一个基类对象的多个拷贝。...(2)被虚拟继承的基类,叫做虚基类。虚基类实际指的是继承的方式,而非一个基类,是动词,而非名词。 (3)为了实现虚拟继承,派生类对象的大小会增加4。...这个增加的4个字节,是因为当虚拟继承时,无论是单虚继承还是多虚继承,派生类需要有一个虚基类表来记录虚继承关系,所以此时子类需要多一个虚基类表指针,而且只需要一个即可。...(4)虚拟继承中,虚基类对象是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的,派生类的构造函数的成员初始化列表中必须列出对虚基类构造函数的调用;如果未列出,则表示使用该虚基类的缺省构造函数。...因为虚拟继承只是表名某个基类的对象在派生类对象中只被构造一次,而在本例中类Student和Employee对象在EGStudent对象中本来就不会被构造多次,所以不将它们申明虚基类也是完全可以的。

    1.1K20

    C# 在构造函数内调用虚方法

    Resharper 对在构造函数内调用虚方法会有警告。...原因 基类构造函数的执行要早于子类构造函数 基类构造函数中对于虚方法的调用,实际调用的是子类中重写的虚方法 基于以上两个原因,如果代码是这样的,就会出现意料之外的问题: 基类的构造函数调用了虚方法 这个虚方法在子类中有重写...,而且虚方法中调用了在子类构造函数中才初始化的变量 因为此时子类构造函数还没有调用,所以就会出现初始化异常(如常见的空引用异常,或者其它的业务没有初始化造成的异常) 如何处理 看有没有其它实现方案 看业务是否满足出现...BUG 的条件,如果不满足,那就忽略提示,但要写注释提示相关问题的存在 可能会出现BUG,那就必须得找其它方案了 参考文章: [C#解惑] #1 在构造函数内调用虚方法 - 麒麟.NET - 博客园

    53200

    #1在构造函数内调用虚方法 | TW洞见

    谜题 在C#中,用virtual关键字修饰的方法(属性、事件)称为虚方法(属性、事件),表示该方法可以由派生类重写(override)。...我们在构造函数中调用虚方法,碍着ReSharper什么事儿了? 其实这个警告就是提醒我们不要在非封闭类型的构造函数内调用虚方法或虚属性。但为什么这样做不合适呢?在解惑之前,我们先来了解两个概念。...我们稍微改造一下虚方法调用的那个例子。...Virtual member call in constructor的警告是因为,对于Base b = new Derived();这样的代码: 基类构造函数的执行要早于子类构造函数 基类构造函数中对于虚方法的调用...,实际调用的是子类中重写的虚方法 因此,ReSharper会警告我们,这么做存在隐患。

    1.5K110

    如何重写object虚方法

    在 C# 中 Object 是所有类的基类,所有的结构和类都直接或间接的派生自它。...前面这段话可以说所有的 C# 开发人员都知道,但是我相信其中有一部分程序员并不清楚甚至不知道我们常用的 ToString 、 Equals 和 GetHashCode 虚方法都来自于 Object 类,...当我们在对象上调用 ToString 时默认返回的是类的完全限定名称,比如说我们在 System.IO.File 对象上调用这个方法,就会返回字符串 System.IO.File ,这个结果往往并不是我们所需要的结果并且这个结果也没有什么意义...在 C# 中我们可以利用 object 类或者它的派生类中的 ReferenceEquals 静态方法来判断对象之间的同一性。...; 判断哈希码是否相等,这一步需进行短路操作和字段比较; 在基类的 Equals 方法被重写的前提下,必须检查基类的 Equals 方法; 判断关键字段的值是否相等; 重写 GetHashCode 方法

    1K10

    JavaScript中的抽象类和虚方法

    一:抽象类与虚方法 虚方法是类成员中的概念,是只做了一个声明而未实现的方法,具有虚方法的类就称之为抽象类,这些虚方法在派生类中才被实现。...抽象类是不能实例化的,因为其中的虚方法并不是一个完整的函数,不能被调用。所以抽象类一般只作为基类被派生以后再使用。 和类的继承一样,JavaScript并没有任何机制用于支持抽象类。...当然,如果希望在基类中添加虚方法的一个定义,也是可以的,只要在派生类中覆盖此方法即可。...(); //调用了一个虚方法 }, oninit:function(){} //虚方法是一个空方法,由派生类实现 } 实例 仍然以prototype-1.6.1为例,其中定义了一个类的创建模型...但实际上可以把Class.create()返回的类看作所有类的共同基类,它在构造函数中调用了一个虚方法initialize,所有继承于它的类都必须实现这个方法,完成构造函数的功能。

    4.8K22

    【C++ 语言】面向对象 ( 继承 | 重写 | 子类调用父类方法 | 静态多态 | 动态多态 | 虚函数 | 纯虚函数 )

    文章目录 类的继承 方法的重写 子类中调用父类方法 多态 虚函数 虚函数示例 纯虚函数 相关代码 类的继承 ---- 1....外部通过子类调用父类方法 : 如果调用的方法在子类中没有重写 , 那么调用的就是父类的方法 ; //在栈内存中创建一个 Child 对象, 并调用其重写的父类的方法 Child child; //...虚函数解析 : 在对象调用虚函数方法时 , 系统会查看该对象真正类型是什么类型 , 然后去调用对应类型的方法 ; 对象是使用什么类型的构造函数创建的 , 其真正的类型就是这个类型 , 因此最终调用该类中的虚函数方法...没有子类 : 虚函数在子类继承父类时才有意义 , 根据类型动态判定该调用哪个方法 , 如果一个类没有子类 , 其设置成虚函数没有意义 , 但也不影响程序运行 ; 虚函数示例 ---- 虚函数代码示例解析..." << endl; } }; ③ 调用子类中实现的纯虚函数 : //在栈内存中创建一个 Child 对象, 并调用其重写的父类的方法 Child child; //纯虚函数测试 parent

    2.2K20

    从零开始学C++之继承(三):多重继承、虚继承与虚基类

    只能通过 sofaBed.Bed::weight_ = 10; 访问,但实际上一个sofaBed理应只有一个weight_,下面通过虚基类和虚继承可以解决这个问题。...二、虚继承与虚基类 当派生类从多个基类派生,而这些基类又从同一个基类派生,则在访问此共同基类中的成员时,将产生二义性,可以采用虚基类来解决。...从输出可以总结出: 1、虚基类的成员是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的。...2、在整个继承结构中,直接或间接继承虚基类的所有派生类,都必须在构造函数的成员初始化表中给出对虚基类的构造函数的调用。如果未列出,则表示调用该虚基类的默认构造函数。...3、在建立对象时,只有最远派生类的构造函数调用虚基类的构造函数,该派生类的其他基类对虚基类构造函数的调用被忽略。

    1.3K00

    SystemVerilog中多态与虚方法

    那么为了保证原有平台或数据结构不变,通过对已经有的基类进行引申或者扩展,从而完善整个验证平台。...从基类做扩展并产生新的子类的过程叫类的派生,当一个类被扩展并创建之后,该派生类就继承了其基类的数据成员、属性和方法,这就是类的继承。...继承后的类可以实现以下功能: 1.继承了原来类中的方法,并可以修改 2.添加新的方法 3.添加新的数据成员 在实现以上功能的同时需要满足一定的规则: 1.子类继承父类的所有数据成员和方法 2.子类可以添加新的数据成员和方法...3.子类可以重写父类中的数据成员和方法 4.如果一个方法被重写,其必须保持和父类中原有定义有一致的参数 5.子类可以通过super操作符来引用父类中的方法和成员 6.被声明为local的数据成员和方法只能对自己可见...上述例子中利用了虚方法,如果去掉虚方法,那么情况如下: ex2: 还是上述代码,只是去掉virtual,则仿真结果如下: # this is the class a. # # this is the

    1.5K10

    利用实例巧妙区分“抽象方法”和“虚方法”!

    举例分析方法的不同 下面举个栗子说明一个抽象方法和虚方法的不同用途,以下代码使用C#语言编写,Java等语言思路类似。 抽象方法 比如说有一个基类“动物类”,同时有两个子类“鸟类”和“鸡类”。...这两个类都有公共和特有的属性和方法。 如鸡和鸟都会叫,但是叫声不同, 鸡叫:咯咯咯 鸟叫:叽叽叽 我们就可以在基类“动物类”中定义一个约束“鸟类”和“鸡类”的抽象方法“叫声”。...void cry() { Console.WriteLine("鸡叫:咯咯咯"); } } 主类中分别调用“鸟类”和“鸡类”实现该叫声方法...虚方法的实现代码如下: 由于虚方法并不是必须在抽象类中声明,而是可以在任何非密封类中声明,所以将飞行这一动作声明在基类“动物类”中。...Console.WriteLine("鸡飞的很低"); } } 在主类中分别调用“鸟类”和“鸡类”实现该飞行方法: class Program {

    93730
    领券