草庐IT

c++ - 在复杂的多重继承层次结构中, "virtual"关键字在哪里?

coder 2023-06-03 原文

我了解 C++ 虚拟继承的基础知识。但是,我对究竟需要在何处使用具有复杂类层次结构的 virtual 关键字感到困惑。例如,假设我有以下类:

            A
           / \
          B   C
         / \ / \
        D   E   F
         \ / \ /
          G   H
           \ /
            I

如果我想确保没有一个类在任何子类中出现多次,哪些基类需要标记为virtual?他们全部?或者仅在那些直接从可能具有多个实例的类(即 B、C、D、E 和 F;以及 G 和 H)派生的类上使用它就足够了(但仅限于基类 E,而不是与基类 D 和 F))?

最佳答案

我一起玩弄了一个程序,它可以帮助您研究虚拟基地的复杂性。它将 I 下的类层次结构打印为适合 graphiviz ( http://www.graphviz.org/ ) 的有向图。每个实例都有一个计数器,可以帮助您了解构建顺序。这是程序:

#include <stdio.h>
int counter=0; 



#define CONN2(N,X,Y)\
    int id; N() { id=counter++; }\
    void conn() \
    {\
        printf("%s_%d->%s_%d\n",#N,this->id,#X,((X*)this)->id); \
        printf("%s_%d->%s_%d\n",#N,this->id,#Y,((Y*)this)->id); \
        X::conn(); \
        Y::conn();\
    }
#define CONN1(N,X)\
    int id; N() { id=counter++; }\
    void conn() \
    {\
        printf("%s_%d->%s_%d\n",#N,this->id,#X,((X*)this)->id); \
        X::conn(); \
    }

struct A { int id; A() { id=counter++; } void conn() {} };
struct B : A { CONN1(B,A) };
struct C : A { CONN1(C,A)  };
struct D : B { CONN1(D,B) };
struct E : B,C { CONN2(E,B,C) };
struct F : C { CONN1(F,C) };
struct G : D,E { CONN2(G,D,E) };
struct H : E,F { CONN2(H,E,F) };
struct I : G,H { CONN2(I,G,H) };
int main()
{
    printf("digraph inh {\n");
    I i; 
    i.conn(); 
    printf("}\n");
}

如果我运行它(g++ base.cc ; ./a.out >h.dot ; dot -Tpng -o o.png h.dot ; display o.png),我会得到典型的非虚拟基础树:

添加足够的虚拟性...

struct B : virtual A { CONN1(B,A) };
struct C : virtual A { CONN1(C,A)  };
struct D : virtual B { CONN1(D,B) };
struct E : virtual B, virtual C { CONN2(E,B,C) };
struct F : virtual C { CONN1(F,C) };
struct G : D, virtual E { CONN2(G,D,E) };
struct H : virtual E,F { CONN2(H,E,F) };
struct I : G,H { CONN2(I,G,H) };

..结果是菱形(看数字学习构造顺序!!)

但是如果你把所有的基地都变成虚拟的:

struct A { int id; A() { id=counter++; } void conn() {} };
struct B : virtual A { CONN1(B,A) };
struct C : virtual A { CONN1(C,A)  };
struct D : virtual B { CONN1(D,B) };
struct E : virtual B, virtual C { CONN2(E,B,C) };
struct F : virtual C { CONN1(F,C) };
struct G : virtual D, virtual E { CONN2(G,D,E) };
struct H : virtual E, virtual F { CONN2(H,E,F) };
struct I : virtual G,virtual H { CONN2(I,G,H) };

您会得到一颗具有不同初始化顺序的钻石:

玩得开心!

关于c++ - 在复杂的多重继承层次结构中, "virtual"关键字在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3414639/

有关c++ - 在复杂的多重继承层次结构中, "virtual"关键字在哪里?的更多相关文章

  1. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  2. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  3. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

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

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

  5. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  6. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

  7. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  8. ruby - 安装 Ruby 时遇到问题(无法下载资源 "readline--patch") - 2

    当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub

  9. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  10. ruby - RVM "ERROR: Unable to checkout branch ."单用户 - 2

    我在新的Debian6VirtualBoxVM上安装RVM时遇到问题。我已经安装了所有需要的包并使用下载了安装脚本(curl-shttps://rvm.beginrescueend.com/install/rvm)>rvm,但以单个用户身份运行时bashrvm我收到以下错误消息:ERROR:Unabletocheckoutbranch.安装在这里停止,并且(据我所知)没有安装RVM的任何文件。如果我以root身份运行脚本(对于多用户安装),我会收到另一条消息:Successfullycheckedoutbranch''安装程序继续并指示成功,但未添加.rvm目录,甚至在修改我的.bas

随机推荐