【问题标题】:Constructors cannot be virtual, why? Not a dupe [duplicate]构造函数不能是虚拟的,为什么?不是骗子[重复]
【发布时间】:2011-04-18 18:12:35
【问题描述】:

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

我知道以前有人问过这个问题,但我不明白其他答案中使用的复杂技术词汇。

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

“虚拟”机制适用于逻辑完整(完全构造)的对象。我们知道我们使用构造函数来逻辑地初始化我们的对象。换句话说,直到构造函数完成执行,对象才被完全构造。因此,我们不能有虚拟构造函数。

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

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

上述理由正确吗?答案没有谈到对象的静态和动态类型。

【问题讨论】:

    标签: c++ constructor virtual


    【解决方案1】:

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

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

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

    【讨论】:

    • 但是函数式编程中的代数类型一直使用等效的虚拟构造函数(只需看看Maybe monad),并且存在通过工厂方法实现的(复杂的)解决方案在不支持它们的语言中。所以我会说它们是有意义的并且是必要的。
    • @Konrad:我无法评论函数式语言,它们的构造函数模型是否与 C++ 的构造函数模型足够相似,同样的分析也适用。就虚拟工厂方法而言,除了常规构造函数之外,类偶尔具有虚拟构造函数惯用语clonecreate 非静态成员函数是很有用的。我认为没有必要将它构建到每个对象中,尽管 Java 使用 Cloneable 接口作为启用它的标志相当漂亮。不确定 CRTP 是否可以在没有卷积的 C++ 中实现相同的效果......跨度>
    • @Steve:你一定是最后一个把Cloneable描述为漂亮的人——其他人都已经达成共识,这个接口是complete和完整的disaster,并使用@987654323 @ 代替。
    • @Konrad:我说的是“漂亮”,而不是“完美”;-p 漂亮的部分只是您使用接口标记类以供 VM 复制。 cloneObject 的受保护方法这一事实并不漂亮。如果 Java 有 mixins,Cloneable 将是一个,将提供clone 的公共默认实现,然后基本上就可以工作(尽管可能应该有单独的 deep_clone 和 shallow_clone 接口)。但显然多重继承是邪恶的,所以 Java 睡在它制造的床上......
    • @Steve Jessop:当公共克隆方法有用时,实现提供的 meberwise 克隆是它最可靠的基础。关于深与浅的“混淆”似乎没有根据。克隆有用的许多类型是通用容器。克隆容器的自然行为是尽可能深入地克隆以保留 容器 的语义,但不要克隆其中包含的对象。哪里有歧义?
    【解决方案2】:

    引用The C++ Programming Language

    为了构造一个对象,一个构造函数 需要它的对象的确切类型 是创造。因此,一个 构造函数不能是虚拟的。 此外,构造函数不是 很普通的功能。在 特别是,它与记忆相互作用 日常管理程序 成员函数没有。所以, 你不能有一个指针 构造函数。

    有趣的是,C++ 确实有一个名为virtual constructor惯用语。你可以阅读更多关于here的信息。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

          猜你喜欢
          • 2012-01-20
          • 2011-10-29
          • 1970-01-01
          • 2015-11-12
          • 2012-03-09
          • 2011-09-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多