我在多重继承和菱形问题上遇到了麻烦。
出现问题是因为我的基类构造函数需要一个参数。编译器尝试为我的两个抽象类生成默认构造函数,但失败了,因为默认构造函数无法确定基类的参数。
我不明白为什么我的抽象类要调用基本构造函数。我认为最派生的类是调用虚拟基类构造函数的类。
这是重现我所说内容的代码:
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 eitherM
has no default constructor or overload resolution (13.3) as applied toM
’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/