虚拟继承是否强制基类默认为可构造的
Does virtual inheritance force a base class to be default constructible?
在以下代码中,编译器请求基类X为默认可构造。但是,如果我从类节点的继承中删除virtual关键字,则对成员m_x进行的访问当然会变得不明确,但不再需要classX默认构造函数。
这是什么原因?
#include <iostream>
struct Apply
{
template< typename T >
struct Node : virtual T // this line contains the virtual inheritance
{
template< typename ...Args>
Node( Args... args )
: T( args... )
{}
};
template < typename ...BaseClasses>
struct Inheritance;
template < typename FirstBaseClass, typename ...OtherBaseClasses>
struct Inheritance< FirstBaseClass, OtherBaseClasses... > : FirstBaseClass
, Inheritance< OtherBaseClasses... >
{
template< typename ...Args>
Inheritance( Args... args )
: FirstBaseClass( args... )
, Inheritance< OtherBaseClasses... >( args... )
{
}
};
};
template < >
struct Apply::Inheritance< >
{
template< typename ...Args>
Inheritance( Args... args ){}
};
struct X
{
X(int i){}
int m_x;
};
struct A : Apply::Node< X >
{
A( int i )
: Apply::Node< X >( i )
, m_a( i )
{
}
int m_a;
};
struct B : Apply::Node< X >
{
B( int i )
: Apply::Node< X >( i )
, m_b( i )
{ }
int m_b;
};
struct C : Apply::Node< X >
{
C( int i )
: Apply::Node< X >( i )
, m_c( i )
{ }
int m_c;
};
struct Example : Apply::Inheritance< A, B, C >
{
Example( int i )
: Apply::Inheritance< A, B, C >( i )
{ }
void print( ) const
{
// this line needs the virtual inheritance
std::cout << m_x << std::endl;
std::cout << m_a << std::endl;
std::cout << m_b << std::endl;
std::cout << m_c << std::endl;
}
};
int main()
{
Example ex( 10 );
ex.print( );
return 0;
}
类的初始化顺序如下[class.base.init]:
在非委托构造函数中,初始化按以下顺序进行:
--首先,并且仅对于派生最多的类(1.8)的构造函数,虚拟基类在它们在基类的有向无环图的深度优先从左到右遍历上出现的顺序,其中"从左到右"是派生类基类说明符列表中基类的出现顺序。
您的层次结构是A --> Node<X> --> X
,因此首先要初始化的是X
,因为它是一个虚拟基类。它没有在mem初始值设定项中指定,因此插入了隐式默认构造:
A( int i )
: X() // <== implicit
, Node< X >( i )
, m_a( i )
{
}
由于X
不是默认可构造的,因此会出现该错误。你可以通过明确地提供正确的东西来解决这个问题:
A( int i )
: X(i)
, Node< X >( i )
, m_a( i )
{
您不必担心X
被构造两次,因为虚拟基类只为大多数派生类构造。。。其将是CCD_ 5而不是CCD_。
从@Berry答案开始,修复代码的唯一方法是对虚拟继承的X构造函数进行显式调用。
然而,在类A、B或C中显式调用X的构造是不够的:它必须基本上在任何级别的继承中涉及的每个类中调用!
棘手的是继承<>可变模板类:可变展开的每一步都必须提供对X构造函数的显式调用。
以下是在启用C++11标志的MinGW 4.9.2上运行的代码:
#include <iostream>
template< typename T, typename V >
struct Node : virtual V
{
using Virtual = V; // Added this line
template< typename ...Args >
Node( Args... args )
: V( args... )
{ }
};
template < typename ...BaseClasses>
struct Inheritance;
template < typename FirstBaseClass, typename ...OtherBaseClasses>
struct Inheritance< FirstBaseClass, OtherBaseClasses... >
: FirstBaseClass
, Inheritance< OtherBaseClasses... >
{
template< typename ...Args>
Inheritance( Args... args )
: FirstBaseClass::Virtual( args... ) // added this line
, FirstBaseClass( args... )
, Inheritance< OtherBaseClasses... >( args... )
{ }
};
template < >
struct Inheritance< >
{
template< typename ...Args >
Inheritance( Args... args )
{ }
};
struct X
{
X(int i)
: m_x( i )
{ }
int m_x;
};
struct A : Node< A, X >
{
A( int i )
: X( i ) // added this line
, Node< A, X >( i )
, m_a( i )
{ }
int m_a;
};
struct B : Node< B, X >
{
B( int i )
: X ( i ) // added this line
, Node< B, X >( i )
, m_b( i )
{ }
int m_b;
};
struct C : Node< C, X >
{
C( int i )
: X ( i ) // added this line
, Node< C, X >( i )
, m_c( i )
{ }
int m_c;
};
struct Example : Inheritance< A, B, C >
{
Example( int i )
: X ( i ) // added this line
, Inheritance< A, B, C >( i )
{ }
void print( ) const
{
// this line needs the virtual inheritance
std::cout << m_x << std::endl;
std::cout << m_a << std::endl;
std::cout << m_b << std::endl;
std::cout << m_c << std::endl;
}
};
int main()
{
Example ex( 10 );
ex.print( );
return 0;
}
相关文章:
- 基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)
- 我什么时候会默认(而不是删除)基类中的复制和移动操作
- 为什么为派生类定义复制构造函数需要定义基类的默认构造函数?
- 默认基类初始值设定项
- 派生类是否具有基类的默认构造函数
- 具有虚拟析构函数的基类子类中的默认析构函数
- 如何防止在基类初始化器中调用默认构造函数?
- C++具有默认参数的基类构造函数
- 在调用基类构造函数时声明默认构造函数
- 重载方法的类接受模板和基类 - 如何默认某个方法
- 重载基类中的方法,默认为成员变量
- 默认赋值运算符有权访问基类的私有成员
- 为什么要删除基类的默认复制并移动ctor和赋值
- 正向声明要在基类中使用的派生类会导致缺少默认构造函数错误
- `使用`keyword表示基类中的默认行为
- 基类在派生类构造函数初始化列表时没有默认构造函数
- 警告:X的默认移动分配运算符将多次移动分配虚拟基类Y
- 初始化基类,派生类的构造函数中没有默认构造函数
- 使用指向基类的指针时的默认析构函数
- 虚拟继承是否强制基类默认为可构造的