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

标签 c++ inheritance abstract-class multiple-inheritance diamond-problem

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

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

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

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

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/

相关文章:

java - 为什么子对象调用具有 main 方法的父类(super class)的私有(private)方法?

python - 如何将一个 Python 对象的所有属性复制到另一个对象?

c++ - 在 C++ 中的抽象接口(interface)上实现运算符重载

cocoa - 抽象类或协议(protocol),Cocoa 推荐的做法是什么?

java - 抽象类的公共(public)构造函数是否有充分的理由

c++ - gotoxy() 用户在 C++ 中定义的函数

c++ - DC C++ Windows 句柄

c++ - 虚继承与多态 : Is the cereal library messing with object layout?

C++ 什么时候在堆上分配还是在堆栈上分配?

c++ - Linux 中伪终端的读写问题