用作虚拟基的c++can类具有带参数的构造函数
c++ can classes used as virtual bases have constructors with parameters?
我是C++新手,我试图用一个通用的虚拟继承类构建一个多继承类(请参阅下面的代码)。我的书礼貌地忽略了虚拟继承类的构造函数有参数的情况。下面的代码是我的尝试。如果我在两个派生类中都删除了基类的虚拟继承,代码就可以构建了。但是,如果我保持原样,它就不会构建。(ubuntu下的g++)
我有几个问题:
1) 最不重要的第一点:为什么代码没有构建?
2) 虚拟继承类是否可以具有带参数的构造函数?
3) 如果问题2)是真的,那么如何评估下面的行?
derived(int i,int j, int k):derived1(i,j),derived2(j,k){};
每个派生类都调用基构造函数,每个类都有第二个参数。但派生中只存在基的一个副本,因为它是作为虚拟继承的。我想了解在这种情况下,执行哪些基本构造函数,使用什么参数:j或k?(我不确定这行是否有效)。
#include <iostream>
using namespace std;
class base
{
int x;
public:
base(int i){cout<<"Constructing base "<<i<<endl;x=i;}
~base(){cout<<"Destructing base"<<endl;}
};
class derived1:virtual public base
{
int x1;
public:
derived1(int i,int j): base(j){cout<<"Constructing derived1 " <<i<<endl;x1=i;}
~derived1(){cout<<"Destructing derived1"<<endl;}
};
class derived2:virtual public base
{
int x2;
public:
derived2(int i,int j): base(j){cout<<"Constructing derived2 "<<i<<endl;x2=i;}
~derived2(){cout<<"Destructing derived2"<<endl;}
};
class derived:public derived1, public derived2
{
int z;
public:
derived(int i,int j, int k):derived1(i,j),derived2(j,k){cout<<"Constructing derived "<<k<<endl;z=k;}
~derived(){cout<<"Destructing derived"<<endl;}
};
int main()
{
derived ob(2,3,4);
}
层次结构中的任何类都可以在其mem初始值设定项列表(:
之后的构造函数定义部分)中列出其虚拟基类,但它们中只有一个会实际执行这些构造函数:最派生的类。
让我们想象一下这样的设置:
#include <iostream>
struct V
{
explicit V(char c) { std::cout << c << 'n'; }
};
struct A : virtual V
{
A() : V('a') {}
};
struct B : A, virtual V
{
B() : V('b') {}
};
struct C : B
{
C() : V('c') {}
};
int main()
{
A a; // prints 'a'
B b; // prints 'b'
C c; // prints 'c'
}
【实例】
正如您所看到的,即使所有A
、B
和C
都在其构造函数中初始化V
,但只有派生程度最高的类(您实际创建的对象的类型)执行其初始化程序。
现在,让我们假设我们添加一个类D
,如下所示:
struct D : C
{
D() {}
};
这不会编译—D
没有在其mem初始值设定项列表中列出V
,因此将使用默认构造函数,但这并不存在。
用从derived1
和derived2
派生的derived
来说明您的具体示例:当创建类型为derived
的对象时,derived
是派生最多的类型,因此只有derived
本身的构造函数才能将参数传递给base
构造函数。在创建derived
对象时,derived1
和derived2
的构造函数内对base
的任何初始化都将被简单地忽略。
虚拟基类由最派生类的构造函数初始化,即使最派生类不是直接从它们继承的。
这意味着,如果您的类层次结构包括任何需要构造函数参数的虚拟基类,则派生程度最高的类构造函数必须在其mem初始值设定项列表中命名它们,并在此时提供任何所需的参数。由于虚拟基类是在任何非虚拟基类之前初始化的,因此建议将它们放在初始化器列表中的非虚拟基类前面:
derived(int i, int j, int k)
: base(i) // note: derived does not inherit directly from base
, derived1(i, j)
, derived2(j, k)
{
cout << "Constructing derived " << k << endl;
z = k;
}
这也意味着,如果派生类依赖于传递给虚拟基的特定参数,则应将其标记为final
,这样它就不能从继承;否则,任何继承类都可能传递"错误"的参数。
还要注意,derived1
和derived2
必须为base
提供构造函数参数,即使它们永远不会被使用。这是该语言中的一个小错误,但还没有人费心清理它(DR257通过https://stackoverflow.com/a/32214536/567292)
- C++:使用运算符 = 调用多参数构造函数
- 通过零参数构造函数创建的 glm::mat4 应该包含哪些值?
- 好奇的混合与可变参数构造函数
- 具有默认值的单个参数构造函数是否与默认构造函数相同?
- 为什么我们需要创建一个单参数构造函数来使用临时的无名称对象
- 在可变参数构造函数中初始化常量数组
- C++ 显式多参数构造函数歧义
- 零一参数构造函数
- 可变参数构造函数中的 SFINAE
- 当没有显式关键字与单参数构造函数一起使用时,编译器可以发出警告
- 可变参数类模板和可变参数构造函数
- 确保模板参数类型与其可变参数构造函数的类型匹配
- C++默认参数构造函数与内联初始化优先级
- 如何在 c++ 中将包含复制构造函数的类的参数构造函数称为私有?
- 自动存储中没有无参数构造函数的类对象和异常
- 警告:用两个参数构造函数返回对象时,表达结果未使用
- 如何在C++中调用无参数构造函数
- 在 c++ 中具有多个参数构造函数的模板类存在问题
- 可变参数构造函数优先于用户提供的移动构造函数,除非默认
- 如何从可变参数构造函数参数构造任何对象?