标签:diamond-problem c inheritance abstract-class multiple-inheritance
我在多重继承和钻石问题上遇到了麻烦.
出现此问题是因为我的基类构造函数需要一个参数.编译器尝试为我的两个抽象类生成默认构造函数,但这会失败,因为默认构造函数无法确定基类的参数.
我不明白为什么我的抽象类调用基础构造函数.我认为最派生的类是调用虚基类构造函数的类.
这是重现我正在谈论的代码:
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;
}
我收到以下错误(对于每个合同):
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段,第6个子弹,如果任何子对象没有默认构造函数,则默认的默认构造函数被声明为已删除:
… 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- …
对于具有虚拟基础的类而言,对于虚拟基础的创建没有特殊豁免,即,将删除默认的默认构造函数.
对于抽象类,显然不必从构造函数成员初始化列表中调用虚拟基础.至少,这就是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 ] …
最衍生基础的相关部分在12.6.2第7段,最后一句:
… 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.
标签:diamond-problem,c,inheritance,abstract-class,multiple-inheritance 来源: https://codeday.me/bug/20190724/1524784.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。