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

如果使用vtable实现具有虚函数的类,那么如何实现没有虚函数的类?

在C++中,使用虚函数表(vtable)实现具有虚函数的类。对于没有虚函数的类,编译器不会生成虚函数表,也不会为其分配额外的内存空间。因此,在没有虚函数的类中,不需要实现任何特殊的方式。

以下是一个简单的示例,展示了具有虚函数和没有虚函数的类的区别:

代码语言:cpp
复制
class Base {
public:
    virtual void foo() {
        // ...
    }
};

class Derived : public Base {
public:
    void foo() override {
        // ...
    }
};

class NoVirtual {
public:
    void bar() {
        // ...
    }
};

int main() {
    Base* base = new Derived();
    base->foo(); // 动态绑定,调用Derived::foo

    NoVirtual no_virtual;
    no_virtual.bar(); // 直接调用NoVirtual::bar

    return 0;
}

在这个示例中,Base类具有虚函数foo(),而NoVirtual类没有虚函数。在main()函数中,我们分别创建了BaseNoVirtual类的对象,并调用了它们的成员函数。对于Base类,我们使用了动态绑定,调用了Derived类的foo()函数。对于NoVirtual类,我们直接调用了bar()函数。

总之,对于没有虚函数的类,不需要额外实现任何内容,直接调用成员函数即可。

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

相关·内容

【C++】多态 ⑧ ( 验证指向 虚函数表 的 vptr 指针 | 对比定义了虚函数的类和没有定义虚函数类的大小 )

对比 定义了 虚函数 的类 与 没有定义虚函数的类 的大小 , 其它成员都相同 , 定义了虚函数的类多出了 4 字节 , 多出的 4 字节就是 vptr 指针占用的内存空间 ; 一、验证指向 虚函数表...1 个虚函数 ; 如果 没有虚函数 , 就不会生成虚函数表 ; 如果 类 中有 virtual 虚函数 , 则 该类的 每个对象 中 , 都有一个 指向 虚函数表的 vptr 指针 ; 虚函数表 存储...虚函数指针 : " 虚函数表 " 是 存储 " 类成员函数指针 " 的 数据结构 , 是一个 函数指针数组 , 数组中的元素都是函数指针 , 具体存储的都是 指向 类中的虚函数 的指针 ; 如果 子类...中 , 重写了 父类的 virtual 虚函数 , 那么 C++ 编译器会在 子类 虚函数表 中放入该 子类虚函数的 函数指针 ; 如果 C++ 类中存在 virtual 虚函数 , 在创建对象时 ,...判断两个类的区别 ; 最终得到 , 有 虚函数 的 类 , 比 没有 虚函数 的 类 , 多 4 字节 , 也就是一个指针的大小 , 定义了 虚函数 的类 , 多出的 4 字节就是 vptr 指针的大小

22740

【c++】多态(多态的概念及实现、虚函数重写、纯虚函数和抽象类、虚函数表、多态的实现过程)

2.4.2 析构函数的重写(重点) 如果基类的析构函数为虚函数,那么派生类的析构函数只要定义,无论是否加virtual关键字,都会重写基类析构函数,这是因为编译之后析构函数的名称被统一处理成...为了尽量避免这种疏忽,c++11提供了关键字override,用于检查派生类虚函数是否重写了基类某个函数,如果没有重写,则编译报错。...抽象类有以下特点: 1. 抽象类不能实例化。 2. 抽象类的派生类如果不重写纯虚函数,那么派生类也是抽象类。...如果是多继承的情况,那么派生类继承了多少个带有虚函数的基类,该派生类就有多少张虚函数表。 3....如果派生类重写了基类的虚函数,那么派生类的虚函数表中对应的虚函数地址就会被覆盖成重写的新虚函数地址。 4.

30621
  • 【c++】多态&&虚函数&&抽象类&&继承中的虚函数表详解

    支付宝首先会分析你的账户数据,比如你是新用户、比如你没有经常支付宝支付等等,那么你需要被鼓励使用支付宝,那么就你扫码金额 =random()%99;比如你经常使用支付宝支付或者支付宝账户中常年没钱,那么就不需要太鼓励你去使用支付宝...普通函数的继承是一种实现继承,派生类继承了基类函数,可以使用函数,继承的是函数的实现。...虚函数的继承是一种接口继承,派生类继承的是基类虚函数的接口,目的是为了重写,达成多态,继承的是接口。所以如果不实现多态,不要把函数定义成虚函数 4....nullptr 总结一下派生类的虚表生成:a.先将基类中的虚表内容拷贝一份到派生类虚表中 b.如果派生类重写了基类中某个虚函数,用派生类自己的虚函数覆盖虚表中基类的虚函数 c.派生类自己新增加的虚函数按其在派生类中的声明次序增加到派生类虚表的最后...这里是编译器的监视窗口故意隐藏了这两个函数,也可以认为是他的一个小bug。那么我们如何查看d的虚表呢?

    38510

    【C++】多态 ⑪ ( 纯虚函数和抽象类 | 纯虚函数语法 | 抽象类和实现 | 代码示例 )

    一、纯虚函数和抽象类 1、纯虚函数 纯虚函数 : 在 C++ 语言中 , " 纯虚函数 " 是 特殊类型的 虚函数 , " 纯虚函数 " 在 父类 中 声明 , 但是没有实现 ; 抽象类 : " 纯虚函数..." 的实现 ; 父类 中的 " 纯虚函数 " 为 其若干子类 提供了一个 公共界面 , 用于 接口的 封装 / 设计 , 软件的 模块划分 ; 2、纯虚函数语法 纯虚函数语法 : 函数前 使用 virtual...不能 创建 实例对象 , 只能作为其它类的 父类 ; " 纯虚函数 " 是一种在 父类 中 声明但没有实现 的虚函数 , 其目的是使 父类 成为抽象类 ; 任何从抽象类派生出来的子类都必须提供 纯虚函数...派生类 , 继承 AbstractClass 抽象类 , 实现了 纯虚函数 pureVirtualFunction 函数 ; 实现的 纯虚函数 可以不使用 virtual 修饰 , 在 函数声明 最后添加...子类对象 , 使用 抽象类 指针 调用 纯虚函数 , 由于 父类 的 纯虚函数没有实现 , 实际调用的 是 子类对象的 函数 , 该调用 发生了 多态 ; 代码示例 : #include "iostream

    27430

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

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

    9210

    C++核心准则C.127:包含虚函数的类应该有虚析构函数或保护析构函数‍

    包含虚函数的类通常(大多数情况下)通过指向基类的指针使用。通常,最后一个使用者必须通过指向基类的指针调用delete操作,通常是指向基类的智能指针,因此析构函数应该是公开的虚函数。...稍微特殊一些的情况是:如果不希望支持通过指向基类的指针销毁对象,析构函数应该是保护的非虚函数。参见C.35。...一直这么做的人会产生一个错误的判断。但是准则还是重要的--如果某人使用make_unique申请内存会怎么样?...包含虚函数的类的析构函数要么是公开的虚函数,要么是保护的非虚函数。...提示针对包含虚函数却没有虚析构函数的类的销毁操作。

    78220

    面试题:基类的析构函数为何要声明为虚函数?

    面试题:基类的析构函数为何要声明为虚函数? 在 C++ 中,一个类的析构函数用于释放它的实例占用的资源。如果没有正确地释放这些资源,就可能会导致内存泄漏和其他严重的问题。...基类的析构函数到底是否需要声明为虚函数取决于你是否会使用继承体系。 当使用继承时,如果一个基类指针指向了一个派生类对象,当对指针进行 delete 操作时,应该同时调用基类和派生类的析构函数。...如果基类的析构函数不是虚拟函数,则运行时不能确认要调用哪个析构函数。如果它是虚拟的,则始终将调用最实际对象的析构函数。...总结 在使用继承时,应该将基类的析构函数声明为虚函数,这样可以确保在运行时删除派生类对象时同时调用基类和派生类的析构函数。否则运行时不能确认要调用哪个析构函数,并且可能导致内存泄漏和其他问题。...需要注意的是,每个具有虚函数的对象都包含一个指向虚函数表格(vtable)的指针,从而增加了内存开销,但是这种开销相对于可靠性和程序稳定性的提升来说是值得的。

    4700

    C+虚函数实现多态性的思考

    在C++中,类是一种规范,它描述了这种新型数据格式,对象是根据这种规范构造的特定数据结构。类中的虚函数和多态性的实现有着前因后果的关系。...在Houdini的HDK文档中很多类成员方法声明语句前有virtual这个单词,这就是所谓的虚函数。 来简单描述虚函数是如何实现多态性的?...先来定义一个基类叫CG_Software 虚函数意味着基类希望子类能提供自己的实现代码,但基类也提供了一个缺省的虚函数实现,在子类不复写这个虚函数的情况作为备选方案 有了基类,就可以派生具体的CG软件了...,比如Maya类 Houdini类 牛逼的CG艺术家 给我什么软件我就怎么建模 给我什么软件我就怎么做特效 接下来有意思的事情就发生了,来实例化使用这些类 上面的代码演示了最经典的多态性,给Andy不同的软件...从虚函数的复写到函数多态性的实现过程。

    787100

    C++编程经验(2):为虚基类做虚析构函数的必要性

    这个要提一下,如果记不住就记住:如果不做虚析构函数,会有内存泄漏 解释 定义一个基类的指针p,在delete p时,如果基类的析构函数是虚函数,这时只会看p所赋值的对象,如果p赋值的对象是派生类的对象,...就会调用派生类的析构函数;如果p赋值的对象是基类的对象,就会调用基类的析构函数,这样就不会造成内存泄露。...如果基类的析构函数不是虚函数,在delete p时,调用析构函数时,只会看指针的数据类型,而不会去看赋值的对象,这样就会造成内存泄露。 多少学点设计模式就清楚了。...接下来是一个子类 class Inherit :public Base{ //此处省去,一切从简 }; //重点看调用 int main() { Base *p = new Inherit; //这种方式的调用...,这时候有没有虚析构就不一样了 delete p; Base *q = new Base; delete q; return 0; }

    59710

    C++中虚函数多态实现的原理刨析

    在深入探究多态实现原理前,先要理解多态的意思和虚函数实现的条件 多态: 不同类的对象对同一消息的不同响应 注意: 虚函数实现条件 : 1.有继承关系 2.子类重写父类的虚函数 动态多态的使用...: 父类的指针或者引用指向子类的对象 多态实现的原理探究: 未写虚函数前: #include using namespace std; class Animal { public:...未写虚函数前,空对象a的大小为1,写了虚函数后,对象a的大小为4,是因为此时a里面存放了一个vfptr虚函数(表)指针,指针大小无论类型均为4个字节大小 该虚函数指针指向一个虚函数表 当子类未重写父类虚函数时...(即cat类里面没有与animal类里面speak同名的函数): ?...当发生虚函数重写时,子类会把自己的虚函数覆盖掉之前父类的虚函数 因此当父类的指针或者引用指向子类对象的时候,会发生多态,你传入的是cat对象,就去cat的虚函数表中找speak函数的入口地址

    46010

    c++ 继承类强制转换时的虚函数表工作原理

    本文通过简单例子说明子类之间发生强制转换时虚函数如何调用,旨在对c++继承中的虚函数表的作用机制有更深入的理解。...因为在类child2的虚函数表中,共存在三个函数,分别为f() b() a(),其中函数b()是第二个,因此编译器就会把对象c1对应的内存来当做类child2的内存布局来解析(注意内存里的内容不变,还是...c1的,即为类child1的内存布局,在这里只有虚函数表),此时在类child1的虚函数表中也找第二个函数,找到了函数a(),因此输出“child1::a()”,运行正常。...但这种行为可能是危险的,若使用的内存布局并不适合真实内存,很可能造成访问越界等问题(如上例中的“pc21->a();”,这次就在类B的虚函数表中找第三个函数,结果没有找到(访问越界),函数运行时崩溃。)...2、通过上述例子可知,虚函数在虚函数表中的存储顺序是与声明顺序一致的,而不是虚函数名字的字符串排序,如本例中为f() b() a(),虽然编程时的自动补全提示框中显示的顺序是a() b() f(),但可能已经经过内部优化

    1.2K30

    《挑战30天C++入门极限》C++中类的多态与虚函数的使用

    C++中类的多态与虚函数的使用   类的多态特性是支持面向对象的语言最主要的特性,有过非面向对象语言开发经历的人,通常对这一章节的内容会觉得不习惯,因为很多人错误的认为,支持类的封装的语言就是支持面向对象的...,对于类的重载来说,明确的,不同类的对象,调用其类的成员函数的时候,系统是知道如何找到其类的同名成员,上面代码中的a.ShowMember();,即调用的是Vehicle::ShowMember(),b.ShowMember...,而函数test的形参却只是Vehicle类的引用,按照类继承的特点,系统把Car类对象看做是一个Vehicle类对象,因为Car类的覆盖范围包含Vehicle类,所以test函数的定义并没有错误,我们想利用...,当调用DelPN(a);后,在析构的时候,系统成功的确定了先调用Car类的析构函数,而如果将析构函数的virtual修饰去掉,再观察结果,会发现析构的时候,始终只调用了基类的析构函数,由此我们发现,多态的特性的...virtual修饰,不单单对基类和派生类的普通成员函数有必要,而且对于基类和派生类的析构函数同样重要。

    70510

    Python|函数式编程|类的函数式实现

    本文参考SICP,Function Abstraction python作为一个现代语言,结合着OOP和FP的多种性质,不同于其他OOP语言,python中的函数具有自己的环境,让我们从这里入手,看看类在...FP中可以如何实现....函数,闭包,其内部名称只可被内部访问,因此,本质上,它可以视为大部分成员都是私有的对象。 那么,函数有什么是public的呢,答案是,返回值,这是函数与外界沟通的桥梁....1 map={"b":b,"c":c} def getitem(index): return map[index] return getitem 我们可以回忆OOP中对象模型是如何实现的...而内部的成员等等都是通过偏移量计算得出。在编译器内部,偏移量又是一张符号表。它不可见于外界,但是同时又被类所知晓。

    52530

    深入解析C++中的虚函数和虚继承:实现多态性与继承关系的高级特性

    这里写目录标题 虚函数 虚函数实现动态绑定 虚继承 抽象类 虚函数 虚函数是在C++中用于实现多态性的一种特殊函数。它通过使用关键字"virtual"进行声明,在基类中定义,可在派生类中进行重写。...动态绑定的关键在于使用virtual关键字将成员函数声明为虚函数,并在基类和派生类中提供相应的实现。...动态多态使用:父类的指针或引用 指向子类对象 重写:函数返回值类型 函数名 参数列表 完全一致叫重写 如果子类中没有堆区数据,可以不用写虚析构和纯虚析构。...如果一个类包含了纯虚函数,那么它就成为了抽象类,无法被直接实例化,只能作为基类来派生其他类。...该函数没有实际的实现,只是作为接口的定义存在。 派生类必须提供对纯虚函数的实现,否则它们也会成为抽象类。

    2.1K10

    从零开始学C++之虚继承和虚函数对C++对象内存模型造成的影响(类对象的大小)

    ,如何实现的呢?...从成员输出的地址和通过虚函数表指针访问到的函数可以画出模型: ? DD::vfdd 的位置跟继承的顺序有关,如果DD先继承的是B2, 那么它将跟在B2::vfb2 的下面。...从输出的虚基类表成员数据和虚函数体可以画出对象内存模型图: ? 上图中vfdd 出现的位置跟继承的顺序有关,如果DD先继承的是B2,那么它将跟在vfb2 的下面。...注意:如果没有虚继承,则虚函数表会合并,一个类只会存在一个虚函数表和一个虚函数表指针(同个类的对象共享),当然也不会有虚基类表和虚基类表指针的存在。...但如果是钻石继承,那么是会存在两份虚函数表和两份虚函数表指针的。 参考: 《深入探索C++对象模型》 C++ primer 第四版 Effective C++ 3rd C++编程规范

    1K00

    C++核心准则C.130:实现多态类的深拷贝时,虚clone函数要比拷贝构造函数赋值运算符好

    of polymorphic classes prefer a virtual clone function instead of copy construction/assignment C.130:实现多态类的深拷贝时...,虚clone函数要比拷贝构造函数/赋值运算符好。‍...如果你真的需要复制语义,就进行深拷贝:提供一个虚的克隆函数,这个函数可以复制实际的派生类型并返回一个指向新对象的所有权指针,同时在派生类中返回派生类型(使用共变量返回类型) 切片问题(slicing...共变量返回类型(covariant return type):当基类的虚函数被派生类覆盖时,如果基类的虚函数返回某个类,而派生类返回该类的派生类,也看做是成功的覆盖。‍...因此,你要么在所有的覆盖都返回unique_ptr,要么使用准则支持库中的onwer。

    66600

    C++核心准则C.35:基类的析构函数要么是公开的虚函数,要么是保护的非虚函数

    为了避免无定义的行为。如果析构函数是公有的,那么调用侧的代码就会尝试使用基类指针销毁派生类的对象,在基类的析构函数为非虚函数时其结果时没有定义的。...如果析构函数时保护的,那么调用侧代码就无法通过基类类型指针销毁派生类对象,这是析构函数就没有必要一定是虚函数。析构函数是保护而不是私有的,这样派生类的析构函数才能调用它。...虚函数定义了派生类的接口,它可以在不关注派生类的情况下使用。如果接口允许对象,那么这个销毁过程应该是安全的。...我们可以想象一种需要保护的虚函数析构函数的情况:当希望允许派生类的对象(只有这个类型)通过基类指针销毁另外一个对象(不是它自己)时。但是我们还没有在实际的开发中遇到这种情况。...拥有虚函数的类的虚函数要么是公开的虚函数,要么是保护的非虚函数。 译者注:拥有虚函数一般就意味着它有派生类。

    1.1K20

    C++纯虚函数 virtual =0

    a) {     (a->vptr[1])(); }     因为派生类和基类的foo()函数具有相同的VTABLE索引,而他们的vptr又指向不同的VTABLE,因此通过这样的方法可以在运行时刻决定调用哪个...纯虚的析构函数并没有什么作用,是虚的就够了。通常只有在希望将一个类变成抽象类(不能实例化的类),而这个类又没有合适的函数可以被纯虚化的时候,可以使用纯虚的析构函数来达到目的。...3.3 多继承中的虚函数 3.4 什么时候使用虚函数      在你设计一个基类的时候,如果发现一个函数需要在派生类里有不同的表现,那么它就应该是虚的。...那么就应该将这个“一样的操作”声明为virtual。     现实中,远不只我举的这两个例子,但是大的原则都是我前面说到的“如果发现一个函数需要在派生类里有不同的表现,那么它就应该是虚的”。...这句话也可以反过来说:“如果你发现基类提供了虚函数,那么你最好override它”。

    1.6K40
    领券