java - 构造函数中的虚函数,为什么语言不同?

标签 java .net c++ language-agnostic

在 C++ 中,当从构造函数中调用虚函数时,它的行为不像虚函数。

我认为第一次遇到这种行为的每个人都感到惊讶,但第二次认为这是有道理的:

只要派生的构造函数还没有被执行,对象就不是还是一个派生的实例。

那么如何调用派生函数呢?前提条件还没来得及设置。示例:

class base {
public:
    base()
    {
        std::cout << "foo is " << foo() << std::endl;
    }
    virtual int foo() { return 42; }
};

class derived : public base {
    int* ptr_;
public:
    derived(int i) : ptr_(new int(i*i)) { }
    // The following cannot be called before derived::derived due to how C++ behaves, 
    // if it was possible... Kaboom!
    virtual int foo()   { return *ptr_; } 
};

Java 和 .NET 完全一样,但他们选择了另一种方式,这可能是最小意外原则的唯一原因?

你认为哪个是正确的选择?

最佳答案

语言定义对象生命周期的方式存在根本差异。在 Java 和 .Net 中,对象成员在任何构造函数运行之前被初始化为零/空,此时对象生命周期开始。所以当你进入构造函数时,你已经得到了一个初始化的对象。

在 C++ 中,对象的生命周期仅在构造函数完成时开始(尽管成员变量和基类在它开始之前已完全构造)。这解释了调用虚函数时的行为,以及为什么在构造函数的主体中存在异常时不运行析构函数。

Java/.Net 中对象生命周期定义的问题在于,当对象已初始化但构造函数尚未运行时,很难确保对象始终满足其不变量,而不必考虑特殊情况。 C++ 定义的问题在于,您有一段奇怪的时期,对象处于不确定状态且未完全构造。

关于java - 构造函数中的虚函数,为什么语言不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36832/

相关文章:

c++ - 并行算法寻找K个最近点

c++ - OOP 设计播放器和 AI 控制单元。动态 Actor ?

java - 使用 war 时组到 IBM Liberty (WLP) 中的角色映射

.net - 如何复制一个文件夹的所有内容(复制文件和文件夹)

java - JBWEB003006 : Handshake failed: java. io.IOException : JBWEB002042: SSL handshake failed, SSL session 中的密码套件是 SSL_NULL_WITH_NULL_NULL

c# - 添加条件格式 OpenXML C#

c# - 如何在 C# 中修复 SQLite 查询?

c++ - 如何创建一个变量模板?

java - 在 Java 中将数组作为方法参数传递

java - 如何使用 JNI 使用 java 程序运行 c 程序