草庐IT

c++ - 您是否需要从所有派生类调用虚拟基类构造函数?即使它们不是最衍生的?

coder 2024-02-15 原文

我在多重继承和菱形问题上遇到了麻烦。

出现问题是因为我的基类构造函数需要一个参数。编译器尝试为我的两个抽象类生成默认构造函数,但失败了,因为默认构造函数无法确定基类的参数。

我不明白为什么我的抽象类要调用基本构造函数。我认为最派生的类是调用虚拟基类构造函数的类。

这是重现我所说内容的代码:

class VirtualBase
{

        public:

                VirtualBase(int initial) :
                        count(initial)
        {}

                int getCount() const
                {
                        return count;
                }

                void increment()
                {
                        count++;
                }

        private:

                int count;

};


class ContractA : public virtual VirtualBase
{

        public:

                virtual void doSomething() = 0;

};

class ContractB : public virtual VirtualBase
{

        public:

                virtual void doSomethingElse() = 0;

};

class Concrete : public ContractA, public ContractB
{

        public:

                Concrete() : 
                        VirtualBase(0)
        {}

                virtual void doSomething()
                {
                         increment();
                }

                virtual void doSomethingElse()
                {
                        // etc...       
                }

};

int main()
{

        Concrete concrete;
        concrete.doSomething();
        concrete.doSomethingElse();
        return 0;
}

我收到以下错误(针对每个契约(Contract)):

main.cpp: In constructor ‘ContractA::ContractA()’:
main.cpp:29:7: error: no matching function for call to ‘VirtualBase::VirtualBase()’
 class ContractA : public virtual VirtualBase
       ^
main.cpp:29:7: note: candidates are:
main.cpp:9:3: note: VirtualBase::VirtualBase(int)
   VirtualBase(int initial) :
   ^
main.cpp:9:3: note:   candidate expects 1 argument, 0 provided
main.cpp:4:7: note: VirtualBase::VirtualBase(const VirtualBase&)
 class VirtualBase
       ^
main.cpp:4:7: note:   candidate expects 1 argument, 0 provided
main.cpp: In constructor ‘Concrete::Concrete()’:
main.cpp:53:17: note: synthesized method ‘ContractA::ContractA()’ first required here 
    VirtualBase(0)
                 ^

最佳答案

您的示例使用 EDG 编译和 clang但它不能用 gcc 编译.我不确定代码是否应该按原样编译,因为抽象基类的构造函数似乎被声明为已删除:根据 12.1 [class.ctor] 第 4 段,第六项,默认的默认构造函数被声明为已删除,如果任何子对象都没有默认构造函数:

... A defaulted default constructor for class X is defined as deleted if: ...

  • ...
  • any potentially constructed subobject, except for a non-static data member with a brace-or-equalinitializer, has class type M (or array thereof) and either M has no default constructor or overload resolution (13.3) as applied to M’s default constructor results in an ambiguity or in a function that is deleted or inaccessible from the defaulted default constructor, or
  • ...

在创建virtual 基类方面,对于具有virtual 基类的类没有特殊豁免,即默认的默认构造函数将被删除。

对于抽象类,显然没有必要从构造函数成员初始化列表中调用虚基类。至少,这是 12.6.2 [class.base.init] 第 8 段根据其注释所说的:

In a non-delegating constructor, if a given potentially constructed subobject is not designated by a meminitializer-id (including the case where there is no mem-initializer-list because the constructor has no ctorinitializer), then

  • if the entity is a non-static data member that has a brace-or-equal-initializer and either
  • the constructor’s class is a union (9.5), and no other variant member of that union is designated by a mem-initializer-id or
  • the constructor’s class is not a union, and, if the entity is a member of an anonymous union, no other member of that union is designated by a mem-initializer-id, the entity is initialized as specified in 8.5;
  • otherwise, if the entity is an anonymous union or a variant member (9.5), no initialization is performed;
  • otherwise, the entity is default-initialized (8.5).

[ Note: An abstract class (10.4) is never a most derived class, thus its constructors never initialize virtual base classes, therefore the corresponding mem-initializers may be omitted. — end note ] ...

most derived base的相关部分在12.6.2 paragraph 7, last sentence:

... A mem-initializer where the mem-initializer-id denotes a virtual base class is ignored during execution of a constructor of any class that is not the most derived class.

关于c++ - 您是否需要从所有派生类调用虚拟基类构造函数?即使它们不是最衍生的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38426461/

有关c++ - 您是否需要从所有派生类调用虚拟基类构造函数?即使它们不是最衍生的?的更多相关文章

  1. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  2. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  3. 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%

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

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

  5. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  6. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  7. ruby-on-rails - 跳过状态机方法的所有验证 - 2

    当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested

  8. ruby - Nokogiri 剥离所有属性 - 2

    我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog

  9. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  10. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

随机推荐