【问题标题】:A constructor cannot be virtual构造函数不能是虚拟的
【发布时间】:2012-01-20 08:56:32
【问题描述】:

C++ tutorials in internet 之一中,我发现了以下关于为什么构造函数不能是虚拟的描述

我们不能声明一个虚拟构造函数。我们应该指定确切的 编译时对象的类型,以便编译器可以分配 特定类型的内存。

这个描述正确吗?

我对这句话感到特别困惑:so that the compiler can allocate memory for that specific type

【问题讨论】:

  • 这个解释对了一半,一半是假的。构造函数不能是virtual,因为它根本没有意义。
  • “以便编译器可以为该特定类型分配内存”或多或少是胡言乱语。我们必须在创建对象时指定类型,因为每个对象都有一个类型。 (当然,作为创建对象的一部分,必须根据该类型的大小分配一些内存;但这与指定对象的类型并不真正相关)。
  • @MikeSeymour :那么动态创建的对象呢?那么编译器是否还需要知道对象的类型?
  • @LinuxPenseur:是的,在 C++ 中,对象只能在编译时已知类型的情况下创建。对象只能由声明(包括类型)和新表达式(也包括类型)创建。
  • @LinuxPenseur:不,它是在编译时由程序员在声明或新表达式中指定的。 (例如Thing t;new Whatever)。编译器根据这个生成代码,分配合适的内存,调用正确的构造函数。

标签: c++ constructor virtual-functions


【解决方案1】:

构造函数不能是虚拟的,因为标准是这样规定的。

标准这么说是因为它没有意义。虚拟构造函数会做什么?

虚拟方法用于多态......如果你甚至没有对象,多态应该如何工作?

我们应该在编译时指定对象的确切类型,所以 编译器可以为该特定类型分配内存。

我们应该在编译时指定确切的类型,因为我们想要一个该类型的对象......我发现他们的描述也很混乱。

另外,在段落中并没有说这是构造函数不能是虚拟的原因。它解释了为什么不应该从构造函数中调用虚方法,但仅此而已。

【讨论】:

    【解决方案2】:

    正如 Bjarne 本人在他的 C++ Style and Technique FAQ 中解释的那样:

    虚拟调用是一种在给定部分信息的情况下完成工作的机制。特别是,“虚拟”允许我们调用只知道接口而不知道对象的确切类型的函数。要创建一个对象,您需要完整的信息。特别是,您需要知道要创建的确切类型。因此,“对构造函数的调用”不能是虚拟的。

    【讨论】:

    • 谢谢。请您根据so that the compiler can allocate memory for that specific type 解释一下。短语是否正确?那么为对象动态分配的内存呢?
    • @LinuxPenseur:动态创建对象时,编译器仍然需要知道对象的大小。为此,它需要知道实际类型。
    • @LinuxPenseur:Bjarne 的声明回答了你的 Q,virtualism(动态调度)允许你根据对象的 type 调用函数,但是对象是只有在构造函数调用返回后才完全形成,那么除非对象完全形成,否则如何调用基于它的函数呢?
    • @LinuxPenseur:我 100% 确定。这就是为什么您不能创建不完整类型的实例(例如前向声明的类)的原因 - 既不是静态的也不是动态的。
    • @LinuxPenseur:当然可以!它如何为不知道对象大小的对象分配足够的内存?
    【解决方案3】:

    这是正确的,尽管在我的拙见中它没有抓住重点。

    构造函数设置虚拟调度,即将右指针指向当前类的函数。如果构造函数可以是虚拟的,那么谁会事先设置虚拟构造函数?会有一个可怕的先有鸡还是先有蛋的问题。

    然而,有一个成语叫做“虚拟构造函数”,其中类的静态成员返回一个带有合适类的基类指针:

    class A {
        static A* create();
        virtual ~A();
    };
    
    class B : public A { ... };
    
    A* A::create() { return new B(); }
    

    【讨论】:

    • 虚拟构造函数用于从基类引用创建对象的副本。你展示它的方式,它不是很有用。
    • @BjörnPollex:你的意思是一个虚函数,它返回调用它的对象的副本,对吧?我在“虚拟复制构造函数”一词下知道这个概念。我展示的概念对于完全隐藏调用代码的实现类很有用。
    • 这有点道理。尽管这种情况不涉及任何虚拟(多态返回类型除外)。实际上,要使您的代码正常工作,A::create 必须是 static,它与 virtual 互斥。
    • 我刚刚检查过,C++ FAQ 将这两种变体都称为虚拟构造函数习语。尽管您的示例仍然需要修改。 A::create 必须是虚拟的(或者纯虚拟是 A 是抽象的),并且必须在 B 中被覆盖。
    • @BjörnPollex:是的,static 丢失了(而且很重要),抱歉。已编辑。是的,“虚拟构造函数”并不是真正的虚拟,而是尝试模拟与虚拟函数类似的行为(对基类的函数调用,对类的部分了解)。
    【解决方案4】:

    构造函数如何能够成为virtualvirtual 表示对该函数的调用结果由对象的动态类型决定。在构造之前,没有对象可以这样做。

    教程用语的方式,构造函数是什么,也是假的。您需要指定确切的类型,否则您声明的内容将不会被视为构造函数,并且不允许使用没有返回类型的函数。

    【讨论】:

      【解决方案5】:

      只是补充一下已经说过的,还有虚拟构造函数设计模式,也称为factory method或工厂函数:

      ...它处理创建对象(产品)的问题,而不指定将要创建的对象的确切类

      【讨论】:

        猜你喜欢
        • 2010-09-09
        • 2011-04-18
        • 2012-04-13
        • 2011-07-16
        • 2016-01-22
        • 2015-12-31
        • 1970-01-01
        • 2012-09-02
        相关资源
        最近更新 更多