如何避免在 base class 初始值设定项中调用默认构造函数?
How do I keep from calling default constructor in base class intializers?
我正在尝试构造 Derived3
,以便在初始化 d2
时调用非默认构造函数。我原以为当 d2
被初始化时, none 的默认构造函数会被调用。使用此代码:
#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
为什么会发生这种情况以及如何实现预期的行为?
当您虚拟继承一个基 class 时,在所有情况下,虚拟继承的基 class 都可以被认为总是所谓的直接上级 class "most-derived" class。如下更改 Derived3
构造函数:
Derived3(std::string message) : Derived1(message), Derived2(message),
Base(message)
Base
实际上也是 Derived3
的基础 class,因为它实际上是从 Derived1
(和 Derived2
)继承的。这就是虚拟继承。
如果您不希望 Base
被默认构造,您必须在此处自行调用适当的构造函数。
即使您没有明确声明 Derived3
继承自 Base
,它实际上继承了它,因此您可以从 Derived3
.
调用其构造函数
请注意,如果您将 Derived4
声明为 Derived3
的子 class,则不会调用此处 Base
的构造函数。 Derived4
将无形中继承Base
,由其负责构建
当您虚拟继承 classes 时,真正发生的是 您声明的每个 构造函数都可以被认为是of as 实际上产生了两个实际的构造函数,实际上:一个构造函数负责构造所有虚拟继承的 classes,另一个构造函数不负责。您在上面声明的 Derived3
构造函数:您实际上最终得到了两个构造函数。一个的价格是两个:一个可以构造 Base
,一个不会。将构造Base
的那个在直接构造Derived3
时使用,并且是最派生的class。第二个构造函数是相同的,只是它不会构造 Base
,如果 Derived3
的子 class 被实例化,它就会被使用。您将其视为一个构造函数,但编译器会做更多的工作,创建两个构造函数,并确保在需要构造某些东西时使用正确的构造函数。
我正在尝试构造 Derived3
,以便在初始化 d2
时调用非默认构造函数。我原以为当 d2
被初始化时, none 的默认构造函数会被调用。使用此代码:
#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
为什么会发生这种情况以及如何实现预期的行为?
当您虚拟继承一个基 class 时,在所有情况下,虚拟继承的基 class 都可以被认为总是所谓的直接上级 class "most-derived" class。如下更改 Derived3
构造函数:
Derived3(std::string message) : Derived1(message), Derived2(message),
Base(message)
Base
实际上也是 Derived3
的基础 class,因为它实际上是从 Derived1
(和 Derived2
)继承的。这就是虚拟继承。
如果您不希望 Base
被默认构造,您必须在此处自行调用适当的构造函数。
即使您没有明确声明 Derived3
继承自 Base
,它实际上继承了它,因此您可以从 Derived3
.
请注意,如果您将 Derived4
声明为 Derived3
的子 class,则不会调用此处 Base
的构造函数。 Derived4
将无形中继承Base
,由其负责构建
当您虚拟继承 classes 时,真正发生的是 您声明的每个 构造函数都可以被认为是of as 实际上产生了两个实际的构造函数,实际上:一个构造函数负责构造所有虚拟继承的 classes,另一个构造函数不负责。您在上面声明的 Derived3
构造函数:您实际上最终得到了两个构造函数。一个的价格是两个:一个可以构造 Base
,一个不会。将构造Base
的那个在直接构造Derived3
时使用,并且是最派生的class。第二个构造函数是相同的,只是它不会构造 Base
,如果 Derived3
的子 class 被实例化,它就会被使用。您将其视为一个构造函数,但编译器会做更多的工作,创建两个构造函数,并确保在需要构造某些东西时使用正确的构造函数。