虚函数机制参考虚拟构造函数

时间:2012-08-29 12:11:55

标签: c++ constructor compiler-errors runtime-error vtable

这是在一次采访中向我提出的问题。

如果在编译时创建了Vtable,并且在运行时将vptr分配给了对象,那么如果我们的类中有虚拟构造函数,为什么编译器会给出编译时错误?

我解释了整个机制。但他对'为什么编译时错误而不是运行时错误'

更感兴趣

我告诉他,C ++指南是这样的,因此编译器会在编译时发送错误。

你能否告诉我同样的原因

4 个答案:

答案 0 :(得分:9)

简单回答的棘手问题 - 因为C++中有 no 虚拟构造函数。


ISO标准,ISO / IEC 14882:2003和ISO / IEC 14882:2011,12.1构造函数,第4点:

  

构造函数不应为虚拟(10.3)或静态(9.4)。可以为const,volatile或const volatile对象调用构造函数。构造函数不应声明为const,volatile或const volatile(9.3.2)。 const和volatile语义(7.1.5.1)不适用于正在构造的对象。只有当派生的对象(1.8)的构造函数结束时,这种语义才会生效。

这可以在编译时捕获。

答案 1 :(得分:5)

  

为什么编译时错误而不是运行时错误?

运行时发生异常情况时会发生运行时错误。当编译器检测到C ++标准不允许特定构造作为有效的C ++构造时,会发生编译时错误 C ++标准不允许将构造函数标记为virtual。因此,编译器将其检测为违反语言语法规则并标记错误。

至于回答为什么在C ++中不允许使用虚构造函数 Bjarne在他的常见问题页面上回答Q:

  

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

答案 2 :(得分:3)

语言规则不允许,因为拥有虚拟构造函数没有意义。如何调用此构造函数? C ++中用于构造某个基类的不同派生实例的常用方法是工厂方法:

#include <memory>

// the parameters determine the derived type to be instantiated.
std::unique_ptr<IFoo> fooFactory(some parameters);

注意 smart pointer的选择应由所有权政策决定。此示例使用唯一所有权。

答案 3 :(得分:-1)

在C ++中,“虚拟”意味着所做的事情将在运行时依赖于对象的有效类,而不仅仅取决于变量的类型。

“虚拟”构造函数是没有意义的东西,因为你还没有一个对象(你想构建一个对象)所以你没有任何类可以依赖它做决定。

有时使用“虚拟构造函数”C ++中的目标是一种模式,在这种模式中,您可以在不知道确切类的情况下构建对象...例如:

class Document {
    public:
        static Document *create(...);
    private:
        Document(...);
};

...

// Just use Document::create instead of new Document
std::unique_ptr<Document> p = Document::create(...);

在这种情况下,类的用户无法调用构造函数(它是私有的),但是他们只能调用公共的静态方法,并且会返回指向实例的指针。构造本身将由此函数处理,返回的对象不一定是Document实例,而是来自Document的某个类派生的实例。我知道并且没有公开曝光。 这允许例如在运行时根据环境或调用create中指定的参数来确定确切的类。

这称为“虚构造函数”,因为被调用的构造函数将在运行时决定。然而,它与C ++中的虚方法调用不同,因为C ++中的虚拟调度仅依赖于实例的类(但如前所述,对于构造函数没有意义,因为该对象尚不存在,所以你不能根据其真实的类别来决定。)