如何防止在基类初始化器中调用默认构造函数?
How do I keep from calling default constructor in base class intializers?
我试图以这样一种方式构造Derived3
,即在初始化d2
时调用非默认构造函数。我本以为在初始化d2
时,不会调用任何默认构造函数。使用此代码:
#include <string>
#include <iostream>
struct Base
{
Base() : _message("Value initialized by default constructor")
{
std::cout << "Base default constructor called" << std::endl;
}
Base(std::string message) : _message(message)
{
}
std::string _message;
};
struct Derived1 : virtual public Base
{
Derived1() : Base()
{
std::cout << "Derived1 default constructor called" << std::endl;
}
Derived1(std::string message) : Base(message)
{
}
};
struct Derived2 : virtual public Base
{
Derived2() : Base()
{
std::cout << "Derived2 default constructor called" << std::endl;
}
Derived2(std::string message) : Base(message)
{
}
};
struct Derived3 : virtual public Derived1, virtual public Derived2
{
Derived3() : Derived1(), Derived2()
{
std::cout << "Derived3 default constructor called" << std::endl;
}
Derived3(std::string message) : Derived1(message), Derived2(message)
{
}
};
int main()
{
Derived3 d1 = Derived3();
std::cout << d1._message << std::endl; // You get what you expect.
Derived3 d2 = Derived3("Not initialized by default constructor");
std::cout << d2._message << std::endl; // You get what you do not expect.
}
我本以为d2._message
会"Not initialized by default constructor"
,而实际上它是"Value initialized by default constructor"
.完整输出为:
Base default constructor called
Derived1 default constructor called
Derived2 default constructor called
Derived3 default constructor called
Value initialized by default constructor
Base default constructor called
Value initialized by default constructor
预期输出:
Base default constructor called
Derived1 default constructor called
Derived2 default constructor called
Derived3 default constructor called
Value initialized by default constructor
Not initialized by default constructor
为什么会发生这种情况,我如何获得预期的行为?
当您虚拟继承基类时,在所有情况下,虚拟继承的基类始终被认为是所谓的"最派生"类的直接超类。 更改Derived3
构造函数,如下所示:
Derived3(std::string message) : Derived1(message), Derived2(message),
Base(message)
Base
实际上也是Derived3
的基类,因为它实际上是从Derived1
(和Derived2
)继承的。这就是虚拟继承。
如果您不希望默认构造Base
,则必须在此处自行调用相应的构造函数。
即使你没有明确声明Derived3
继承自Base
,它也虚拟地继承它,因此你可以从Derived3
调用它的构造函数。
请注意,如果你将Derived4
声明为Derived3
的子类,则此处不会调用Base
的构造函数。Derived4
将继承Base
,并负责构建它。
当你有虚拟继承的类时,真正发生的事情是,你声明的每个构造函数都可以被认为是实际上产生了两个实际的构造函数,实际上:一个负责构造所有虚拟继承类的构造函数,另一个不负责构造的构造函数。这Derived3
你在上面声明的构造函数:实际上你最终得到了两个构造函数。两个价格为一个:一个会建造Base
,一个不会。将构造Base
的那个在直接构造Derived3
时使用,并且是派生最多的类。第二个构造函数是相同的,只是它不会构造Base
,并且如果实例化了Derived3
的子类,它就会被使用。你把它看作是一个构造函数,但编译器做了更多的工作,创建了其中的两个,并确保在需要构造某些东西时使用正确的一个。
- 如何在C++中调用默认模板功能参数?
- 为什么即使我调用参数化构造函数也会调用默认构造函数?
- 没有用于调用默认构造函数的匹配函数
- 为什么指针对象没有调用默认构造函数
- 调用默认构造函数时不引用它
- 为什么我的对象声明不调用默认构造函数?
- 为什么要尝试调用默认构造函数?
- 在创建对象向量时,不为每个对象唯一调用默认对象构造函数
- std::map 在 [] 上调用默认构造函数,在 insert() 上调用复制构造函数
- 是否可以从移动构造函数调用默认构造函数?
- 为什么类型变量;不调用默认 CTR
- 声明对象而不调用默认构造函数
- 作为参数的空初始值设定项列表不调用默认构造函数
- 如果类划分为单独的文件,则不调用默认构造函数
- 为什么"S x({})"仅在GCC 7/C++1z模式下调用默认构造函数?
- C++ 继承基构造函数,但仍调用默认派生构造函数
- 在返回语句中调用默认构造函数
- 在构造函数参数中调用默认构造函数
- 如何防止在基类初始化器中调用默认构造函数?
- 如何在以下C 代码中在同一对象上调用默认值和复制构造函数