构造函数不能虚拟,为什么?不是骗局

时间:2010-09-29 10:34:15

标签: c++ constructor virtual

  

可能重复:
  Why do we not have a virtual constructor?

我知道之前已经问过,但我不理解其他答案中使用的复杂技术词汇。

我在社区上读到了构造函数不能虚拟的原因

  

“虚拟”机制适用于逻辑上完整(完全构造)的对象。我们知道我们使用构造函数来逻辑初始化对象。换句话说,在构造函数完成执行之前,对象尚未完全构造。因此,我们不能拥有虚拟构造函数。

     

有一种误解,到那时虚拟表是不完整的,所以我们不能拥有虚拟构造函数。在构造函数开始执行之前,正确构造了虚拟表,并将“this”指针传递给构造函数。而且,虚拟表机制是实现依赖的,并且在C ++标准中找不到位置。因此,使用虚拟表概念争论这个问题是不合逻辑的。

     

现在,当构造函数完成执行任何其他函数时,可以是虚拟的。析构函数也不例外,因为它是一个函数。如果我们使用基类指针来引用派生类对象,使用它,然后删除它,则需要虚拟析构函数。如果我们有虚拟析构函数,使用'delete',从派生到基数开始调用一系列析构函数。但是,如果析构函数中没有“虚拟”,则只调用基类析构函数(而不是派生类)。这(可能)会在程序中产生不一致。

上述原因是否正确?答案没有谈论静态和动态类型的对象。

4 个答案:

答案 0 :(得分:7)

虚拟构造函数没有意义,也没有必要。您调用构造函数的唯一时间是创建对象时。您需要知道对象的类型才能创建它,因此静态和动态类型是相同的,并且要调用的正确构造函数是该类型的构造函数。

这就是他们没有必要的原因。为什么它们没有意义,是在创建对象时,基类构造函数被称为以及派生类构造函数。如果在派生类中重写了基类构造函数,那么这是否意味着基本类构造函数不会被调用?

其他语言有虚拟构造函数,可能是因为这些语言中的构造函数是方法,并且它们只对非静态方法进行虚拟调用。但是那些其他语言(Java和Python脑海中浮现)必须引入特殊的规则,构造函数必须/应该构造它们的基类作为来自构造函数的调用。 C ++就是这样做的(可能在初始化列表中,如果基类构造函数需要参数),使用非虚构造函数,并且没有选项可以使用未初始化的基类子对象输入构造函数的主体。

答案 1 :(得分:3)

引用The C++ Programming Language

  

构造一个对象,一个构造函数   需要它的确切类型   就是创造。因此,a   构造函数不能是虚拟的。   而且,构造函数不是   相当普通的功能。在   特别是,它与记忆相互作用   管理程序以普通的方式进行   成员函数没有。所以,   你不能指向一个   构造

值得注意的是,C ++确实有一个名为 idiom 虚拟构造函数。您可以阅读有关here的更多信息。

答案 2 :(得分:1)

是的,原因是你需要在调用虚函数之前有一个指向完整对象的指针/引用。在调用构造函数时,还没有完整的对象。更重要的是,当你执行new SomeClass()时,你甚至还没有指针 - 在new语句成功完成后返回指针。

答案 3 :(得分:1)

由于构造函数将原始位转换为活动对象,因此无法将虚拟关键字应用于构造函数,并且在存在要调用成员函数的活动对象之前,成员函数无法正常工作。不要将构造函数视为对象上的普通成员函数,而是想象它们是创建对象的静态成员函数。 - C ++常见问题解答