参考虚拟构造函数的虚拟函数机制
Virtual function mechanism with reference to virtual constructor
这是在一次采访中问我的问题。
如果Vtable是在编译时创建的,而vptr
是在运行时分配给对象的,那么如果我们的类中有虚拟构造函数,为什么编译器会在编译时出错呢?
我解释了整个机制。但他更感兴趣的是"为什么编译时错误而不是运行时错误"
我告诉他,C++准则是这样写的,所以编译器在编译时会发送错误。
你能给我提供相同的原因吗
简单答案的小问题-因为C++
中没有虚拟构造函数。
在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)的构造函数结束时,这种语义才会生效。
这可以在编译时捕捉到。
为什么编译时错误而不是运行时错误
当运行时出现异常情况时,会发生运行时错误。而当编译器检测到C++标准不允许特定构造作为有效的C++构造时,就会发生编译时错误
C++标准不允许将构造函数标记为virtual
。因此,编译器检测到它违反了语言语法规则并标记错误。
至于为什么C++中不允许使用虚拟构造函数
Bjarne在他的问题页面上回答问题为:
虚拟调用是一种在给定部分信息的情况下完成工作的机制。特别是,"虚拟"允许我们只知道任何接口而不知道对象的确切类型来调用函数。要创建对象,您需要完整的信息。特别是,你需要知道你想要创建的东西的确切类型。因此,"对构造函数的调用"不能是虚拟的。
语言的规则不允许这样做,因为拥有虚拟构造函数是没有意义的。如何调用此构造函数?C++中构造某个基类的不同派生实例的一种常见方法是工厂方法:
#include <memory>
// the parameters determine the derived type to be instantiated.
std::unique_ptr<IFoo> fooFactory(some parameters);
注意智能指针的选择应由所有权策略决定。此示例使用唯一所有权。
在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++中的虚调度只取决于实例的类(但正如前面所说,这对构造函数来说没有意义,因为对象还不存在,所以你不能根据它的真实类来决定)。
- 虚拟决赛作为安全
- PowerPC ppc64le上的Gcc Woverloaded虚拟错误
- 如何在C++中获得"静态纯虚拟"功能?
- C++无法定义虚拟函数 OUTER 类和头文件
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 在模板基类中为继承类中的可选重写生成虚拟方法
- 尝试将unique_ptrs推送到向量时使用纯虚拟函数错误
- 有没有比在库中添加一个并非由所有派生类实现的新虚拟函数更好的设计实践
- 大小虚拟继承中的派生类
- 链接器找不到在虚拟类 c++ 中访问的静态字段的符号
- 使用 C++ 和 i2c 工具从虚拟 i2c 写入和读取
- 重载 -> shared_ptr 个实例中的箭头运算符<interface>,接口中没有纯虚拟析构函数
- 如果整个应用程序是虚拟映射的,为什么 new 会进行系统调用?
- 跨 DLL 边界访问虚拟方法是否安全/可能?
- std::is_trivially_copyable_v 关于虚拟功能
- 虚拟继承的内部机制
- 派生类中函数参数变化的虚函数按常量类型在"function parameter"会破坏虚拟机制吗?
- 参考虚拟构造函数的虚拟函数机制
- 在虚拟析构函数的情况下,虚拟机制是如何工作的
- 为什么纯虚拟机制不考虑继承函数?