首页
学习
活动
专区
工具
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 指针大小

19240

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

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

24030

【c++】多态&&函数&&抽象&&继承中函数表详解

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

33110

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

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

7510

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

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

75720

C+函数实现多态性思考

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

761100

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; }

57110

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

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

44710

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.1K30

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

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

69610

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中对象模型是如何实现...而内部成员等等都是通过偏移量计算得出。在编译器内部,偏移量又是一张符号表。它不可见于外界,但是同时又被所知晓。

51430

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

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

1.2K10

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

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

1K00

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

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

1K20

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。

61900

C++纯函数 virtual =0

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

1.5K40

【C++深度探索】全面解析多态性机制(二)

2.派生如果没有函数,派生中有函数那么函数表和上面的一致。...如下图所示: 但是如果中有函数表,那么派生如何继承呢?...综上所述,如果派生和基都定义了自己函数,并且基函数没有在派生中重写的话,那么派生函数地址会存放在派生继承那部分函数表中末尾,并且基定义对象和派生定义对象函数地址是不同...综合这三种情况 如果没有函数,子类有函数那么子类会自己生成一个函数表来存放自己函数如果函数,子类也有自己函数那么子类中函数地址会存放在子类继承那部分函数表中末尾...如果只是完成了函数覆盖而没有通过基对象指针或引用调用,或者只有第二个条件都无法完成多态实现。 多态实现两个条件缺一不可。

8910
领券