草庐IT

c++ - 基类的填充会被复制到派生类中吗?

coder 2024-02-23 原文

最近,我一直在阅读“inside the c++ object model”。它说基类中使用的填充也应该复制到派生类中,以防你想将基类分配给派生类。于是,我在64位电脑下进行测试:

    class A {
    public:
        int valA;
        char a;
    };
    class B : public A {
    public:
        char b;
    };
    class C : public B {
    public:
        char c;
    };
    int main(){
        std::cout << sizeof(A) << " " << sizeof(B) << " " << sizeof(C) 
        << std::endl;
        C c;
        printf("%p\n%p\n%p\n",&c,&c.b,&c.c);
    }

结果如下:

    8 12 12

    0x7ffd22c5072c

    0x7ffd22c50734

    0x7ffd22c50735

那么为什么 C 和 B 的大小一样呢?虽然貌似B用了A中的3字节padding。

最佳答案

So why is C the same size of B?

因为 B 的尾部填充被 C::b 重用。填充可以重复使用,因为 B 不是 POD(普通旧数据)类(因为它不是标准布局类)。

Although it seems that B used the 3 byte padding in A.

A 的 padding 不能被 B 的其他子对象重用,因为 A 是一个标准的布局类并且可以简单地复制,即A 是一个 POD 类。


will the padding of base class be copied into the derived class?

我想您不是要问复制,而是要问派生类的基类子对象是否具有与单个类型相同的填充。

答案是,从上面可以推导出:填充将是相同的,除了尾部填充可以重新用于其他子对象,除非基类是 POD,在这种情况下它的填充不能被重复使用。

在padding可能被重用的情况下,是否会被标准没有规定,并且编译器之间存在差异。


Please explain or link to a definition of "standard layout types".

当前标准草案:

[basic.types]

... Scalar types, standard-layout class types ([class.prop]), arrays of such types and cv-qualified versions of these types are collectively called standard-layout types.


[class.prop] (in older versions of the standard, these may be found under [class] directly)

A class S is a standard-layout class if it:

  • (3.1) has no non-static data members of type non-standard-layout class (or array of such types) or reference,

  • (3.2) has no virtual functions and no virtual base classes,

  • (3.3) has the same access control for all non-static data members,

  • (3.4) has no non-standard-layout base classes,

  • (3.5) has at most one base class subobject of any given type,

  • (3.6) has all non-static data members and bit-fields in the class and its base classes first declared in the same class, and

  • (3.7) has no element of the set M(S) of types as a base class, where for any type X, M(X) is defined as follows.107 [ Note: M(X) is the set of the types of all non-base-class subobjects that may be at a zero offset in X. — end note]

    • (3.7.1) If X is a non-union class type with no (possibly inherited) non-static data members, the set M(X) is empty.

    • (3.7.2) If X is a non-union class type with a non-static data member of type X0 that is either of zero size or is the first non-static data member of X (where said member may be an anonymous union), the set M(X) consists of X0 and the elements of M(X0).

    • (3.7.3) If X is a union type, the set M(X) is the union of all M(Ui) and the set containing all Ui, where each Ui is the type of the ith non-static data member of X.

    • (3.7.4) If X is an array type with element type Xe, the set M(X) consists of Xe and the elements of M(Xe).

    • (3.7.5) If X is a non-class, non-array type, the set M(X) is empty.

项目 (3.6) 适用于这种情况。 B 的一些成员没有首先在 B 中声明。特别是,B::A::valA 和 B::A::a 首先在 A 中声明。更友好的描述规则的方式是:类必须有没有直接成员,或者它的祖先都不能有成员。在这种情况下,基类和派生类都有成员,因此它不是标准布局。

关于c++ - 基类的填充会被复制到派生类中吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52818411/

有关c++ - 基类的填充会被复制到派生类中吗?的更多相关文章

  1. ruby - 我需要将 Bundler 本身添加到 Gemfile 中吗? - 2

    当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/

  2. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby - 匹配大写字母并用后续字母填充,直到一定的字符串长度 - 2

    我有一个驼峰式字符串,例如:JustAString。我想按照以下规则形成长度为4的字符串:抓取所有大写字母;如果超过4个大写字母,只保留前4个;如果少于4个大写字母,则将最后大写字母后的字母大写并添加字母,直到长度变为4。以下是可能发生的3种情况:ThisIsMyString将产生TIMS(大写字母);ThisIsOneVeryLongString将产生TIOV(前4个大写字母);MyString将生成MSTR(大写字母+tr大写)。我设法用这个片段解决了前两种情况:str.scan(/[A-Z]/).first(4).join但是,我不太确定如何最好地修改上面的代码片段以处理最后一种

  5. ruby - 我可以将我的 README.textile 以正确的格式放入我的 RDoc 中吗? - 2

    我喜欢使用Textile或Markdown为我的项目编写自述文件,但是当我生成RDoc时,自述文件被解释为RDoc并且看起来非常糟糕。有没有办法让RDoc通过RedCloth或BlueCloth而不是它自己的格式化程序运行文件?它可以配置为自动检测文件后缀的格式吗?(例如README.textile通过RedCloth运行,但README.mdown通过BlueCloth运行) 最佳答案 使用YARD直接代替RDoc将允许您包含Textile或Markdown文件,只要它们的文件后缀是合理的。我经常使用类似于以下Rake任务的东西:

  6. ruby - 使用 `+=` 和 `send` 方法 - 2

    如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

  7. ruby - 如何计算 Liquid 中的变量 +1 - 2

    我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我

  8. arrays - Ruby 数组 += vs 推送 - 2

    我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“

  9. ruby - 如何在 ruby​​ 中复制目录结构,不包括某些文件扩展名 - 2

    我想编写一个ruby​​脚本来递归复制目录结构,但排除某些文件类型。因此,给定以下目录结构:folder1folder2file1.txtfile2.txtfile3.csfile4.htmlfolder2folder3file4.dll我想复制这个结构,但不包含.txt和.cs文件。因此,生成的目录结构应如下所示:folder1folder2file4.htmlfolder2folder3file4.dll 最佳答案 您可以使用查找模块。这是一个代码片段:require"find"ignored_extensions=[".cs"

  10. ruby - 如何用递增的值填充数组 Ruby - 2

    我正在尝试解决http://projecteuler.net/problem=1.我想创建一个方法,它接受一个整数,然后创建一个包含它前面的所有整数的数组,并将整数本身作为数组中的值。以下是我目前所拥有的。代码不起作用。defmake_array(num)numbers=Array.newnumcount=1numbers.eachdo|number|numbers 最佳答案 (1..num).to_a是您在Ruby中需要做的全部。1..num将创建一个Range对象,以1开始并以任意值num结束是。Range对象有to_a方法通过

随机推荐