C++:具有虚基但没有虚函数的类是多态的并且具有 VTable 吗?

2024-03-16

考虑以下代码:

#include <iostream>
#include <typeinfo>
#include <type_traits>

using namespace std;

struct A { int data; };
struct B1 : A {};
struct B2 : virtual A {};

struct Base1 : virtual A {};
struct Base2 : virtual A {};
struct Derived : Base1, Base2 {};

int main() {
  cout << sizeof(B1) << endl;
  cout << sizeof(B2) << endl;
  cout << sizeof(Derived) << endl;

  cout << std::is_polymorphic<B1>::value << endl;
  cout << std::is_polymorphic<B2>::value << endl;
  cout << std::is_polymorphic<Derived>::value << endl;
  return 0;
}

在我的系统上它打印

4
8
12
0
0
0

这意味着这些类都不是多态的。然而,B1 和 B2 的大小因指针的大小而不同,该指针可能是指向 vtable 的指针。我运行过 gcc-fdump-class-hierarchy并得到:

Vtable for B2
B2::_ZTV2B2: 3u entries
0     4u
4     (int (*)(...))0
8     (int (*)(...))(& _ZTI2B2)

VTT for B2
B2::_ZTT2B2: 1u entries
0     ((& B2::_ZTV2B2) + 12u)

Class B2
   size=8 align=4
   base size=4 base align=4
B2 (0x0x3ca5400) 0 nearly-empty
    vptridx=0u vptr=((& B2::_ZTV2B2) + 12u)
  A (0x0x3c972d8) 4 virtual
      vbaseoffset=-12

这里有一个问题:什么是多态类? “具有 vtable”是否意味着“多态并具有 RTTI”,反之亦然?如果不是,为什么它必须至少有一个虚函数才能成为多态,如果它无论如何都会有 vtable 的话?

看起来多态类的定义与“具有 vtable 的类”不同,因为,正如我们在上面看到的,B2 不是多态类,但具有 vtable,并且正如我认为的那样,应该具有 RTTI。在this http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1529.html#1.2.4.1文档中明确指出“多态 - 即至少有一个虚函数。(这是允许生成的调度代码在类上使用 RTTI 所必需的。)”。


您在这里错过了一个细节:虚拟表是一个实施细节。因此:

  • 该标准定义了多态性类作为可以在多态意义上使用的类:即,行为可以被重写
  • 编译器使用虚拟表来实现标准规定的一些功能/行为,其中恰好包括多态类和虚拟基。

Thus, yes我知道的编译器(MSVC 和那些遵循 Itanium ABI 的编译器,例如 gcc、icc 和 Clang)将使用虚拟表来提供必要的 RTTIdynamic_cast在存在虚拟基的情况下工作...不,这与类是否多态无关。

然而,在切线上,更喜欢组合而不是继承意味着如果没有可以重写的行为,就没有理由从类继承。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++:具有虚基但没有虚函数的类是多态的并且具有 VTable 吗? 的相关文章

  • 将集合绑定到自定义控件属性

    我没有运气尝试将数据集合绑定到我的自定义控件的属性 我已经实现了该控件的字符串属性的机制 在此处提供了一些帮助 并期望集合类型同样简单 但是我无法让它再次工作 这是我的自定义控件视图
  • 通过 SocketCAN 进行 boost::asio

    我正在考虑利用升压阿西奥 http www boost org doc libs 1 49 0 doc html boost asio html从a读取数据套接字CAN http en wikipedia org wiki SocketCA
  • 在 C/C++ 中获得正模数的最快方法

    通常在我的内部循环中 我需要以 环绕 方式索引数组 因此 例如 如果数组大小为 100 并且我的代码要求元素 2 则应该给它元素 98 高级语言 例如 Python 可以简单地使用my array index array size 但由于某
  • 在 C# 中按元素相乘数组具有意想不到的性能

    我想找到按元素相乘两个数组的最佳方法 这是更广泛项目的一部分 其中性能而不是唯一的考虑因素 我今天开始用 C Linqpad 编写一些函数 因此它还没有以任何方式进行优化 下面代码的输出如下 Environment ProcessorCou
  • 何时使用 =default 使析构函数默认?

    尽管对构造函数使用 default 对我来说很清楚 即强制编译器在其他构造函数存在时创建默认构造函数 但我仍然无法理解这两种类型的析构函数之间的区别 那些使用 default 的 那些没有显式定义并由编译器自动生成的 我唯一想到的是 gro
  • 为什么在创建矩阵类时使用向量不好?

    对于我的矩阵类 我做了 template
  • 在 Xamarin 中隐藏软键盘

    如何隐藏软键盘以便在聚焦时显示Entry在 Xamarin forms 便携式表单项目中 我假设我们必须为此编写特定于平台的渲染器 但以下内容不起作用 我创建自己的条目子类 public class MyExtendedEntry Entr
  • 防止 boost::asio::io_context 在空轮询调用时停止

    此代码调用发布的句柄 boost asio io context ioc boost asio post ioc std cout lt lt lol lt lt std endl ioc poll 而这并没有 boost asio io
  • 信号处理程序有单独的堆栈吗?

    信号处理程序是否有单独的堆栈 就像每个线程都有单独的堆栈一样 这是在 Linux C 环境中 来自 Linux 手册页signal 7 http kernel org doc man pages online pages man7 sign
  • ASP.Net Core 内容配置附件/内联

    我正在从 WebAPI 控制器返回一个文件 Content Disposition 标头值自动设置为 附件 例如 处置 附件 文件名 30956 pdf 文件名 UTF 8 30956 pdf 当它设置为附件时 浏览器将要求保存文件而不是打
  • 动态生成的控件 ID 返回为 NULL

    我可以在 Page PreInit 函数中创建动态控件 如何检索控件及其 ID 我的 C 代码用于创建动态控件之一 var btn new WebForms Button btn Text btn ID Addmore btn Click
  • 单例模式和 std::unique_ptr

    std unique ptr唯一地控制它指向的对象 因此不使用引用计数 单例确保利用引用计数只能创建一个对象 那么会std unique ptr与单例执行相同 单例确保只有一个实例属于一种类型 A unique ptr确保只有一个智能指针到
  • Visual Studio Code:如何配置 includePath 以获得更好的 IntelliSense 结果

    我是使用 Visual Studio Code 的完全初学者 我不知道我在做什么 我已经四处搜索 也许还不够 但我找不到像我这样的人如何配置的简单解释c cpp properties json每当我单击带有绿色波浪线下划线的行旁边的黄色灯泡
  • 给出 5 个参数,但在终端中只得到 3 个参数

    我想将一个文件传递给一个c 程序 如果我在 IDE 中执行此操作 test string string lt test txt return argc 5 但在终端上我刚刚得到argc 3 看来 这是因为 什么是 lt 意思是 我正在使用
  • 运行选定的代码生成器时出错:“未将对象引用设置到对象的实例。”错误?

    我已经尝试了所有解决方案 例如修复 VS 2013 但没有用 当您通过右键单击控制器文件夹来创建控制器并添加控制器时 然后右键单击新创建的控制器的操作并选择添加视图 当我尝试创建视图时 就会发生这种情况 它不是一个新项目 而是一个现有项目
  • 是否有相当于 Clang/LLVM 的 .spec 文件,在哪里可以找到参考?

    The gcc驱动程序可以配置为使用特定的链接器 特定的选项和其他细节 例如覆盖系统头 specs files 当前 截至撰写本文时 GCC 版本 4 9 0 的手册此处描述了规范文件 https gcc gnu org onlinedoc
  • 每个数据库多个/单个 *.edmx 文件

    我有一个通过 ADO net 数据服务与数据库交互的项目 数据库很大 近 150 个具有依赖关系的表 该项目几年前开始 当时使用的是数据集 现在我们正在转向实体模型关系 由于我们添加了更多需要使用的表 该模型正在不断增长 这是管理这一切的正
  • C++ Streambuf 方法可以抛出异常吗?

    我正在尝试找到一种方法来获取读取或写入流的字符数 即使存在错误并且读 写结束时间较短 该方法也是可靠的 我正在做这样的事情 return stream rdbuf gt sputn buffer buffer size 但如果streamb
  • C++0x中disable_if在哪里?

    Boost 两者都有enable if and disable if 但 C 0x 似乎缺少后者 为什么它被排除在外 C 0x 中是否有元编程工具允许我构建disable if按照enable if 哦 我刚刚注意到std enable i
  • QFileDialog::getSaveFileName 和默认的 selectedFilter

    我有 getSaveFileName 和一些过滤器 我希望当用户打开 保存 对话框时选择其中之一 Qt 文档说明如下 可以通过将 selectedFilter 设置为所需的值来选择默认过滤器 我尝试以下变体 QString selFilte

随机推荐