簡體   English   中英

從父類ctor調用重寫的方法

[英]Calling an overridden method from a parent class ctor

我嘗試從父類的構造函數中調用重寫方法,並注意到跨語言的不同行為。

C++ - 回聲A.foo()

class A{

public: 

    A(){foo();}

    virtual void foo(){cout<<"A.foo()";}
};

class B : public A{

public:

    B(){}

    void foo(){cout<<"B.foo()";}
};

int main(){

    B *b = new B(); 
}

Java - 回聲B.foo()

class A{

    public A(){foo();}

    public void foo(){System.out.println("A.foo()");}
}

class B extends A{  

    public void foo(){System.out.println("B.foo()");}
}

class Demo{

    public static void main(String args[]){
        B b = new B();
    }
}

C# - 回聲B.foo()

class A{

    public A(){foo();}

    public virtual void foo(){Console.WriteLine("A.foo()");}
}

class B : A{    

    public override void foo(){Console.WriteLine("B.foo()");}
}


class MainClass
{
    public static void Main (string[] args)
    {
        B b = new B();              
    }
}

我意識到在C ++對象是從層次結構中最頂層的父對象創建的,所以當構造函數調用重寫方法時,B甚至不存在,因此它調用方法的A'版本。 但是,我不確定為什么我在Java和C#中獲得不同的行為(來自C ++)

在C ++中,正如您所正確指出的那樣,對象的類型為A直到A構造函數完成。 該對象實際上在構造期間改變了類型。 這就是使用A類的vtable的原因,因此調用A::foo()而不是B::foo()

在Java和C#中,即使在構造基類期間,也始終使用最派生類型的vtable(或等效機制)。 所以在這些語言中, B.foo()被調用。

請注意,通常不建議從構造函數中調用虛方法。 如果你不是很小心,虛擬方法可能會認為對象是完全構造的,即使不是這種情況。 在Java中,每個方法都隱式虛擬,您別無選擇。

雖然我知道您正在進行實驗,但重要的是要注意以下有效Java第2版,第17項:設計和繼承文檔,或者禁止它

為了允許繼承,類必須遵守一些限制。 構造函數不得直接或間接調用可覆蓋的方法 如果違反此規則,將導致程序失敗。 超類構造函數在子類構造函數之前運行,因此在子類構造函數運行之前將調用子類中的重寫方法。 如果重寫方法依賴於子類構造函數執行的任何初始化,則該方法將不會按預期運行。

這是一個例子來說明:

public class ConstructorCallsOverride {
    public static void main(String[] args) {
        abstract class Base {
            Base() { overrideMe(); }
            abstract void overrideMe(); 
        }
        class Child extends Base {
            final int x;
            Child(int x) { this.x = x; }
            @Override void overrideMe() {
                System.out.println(x);
            }
        }
        new Child(42); // prints "0"
    }
}

這里,當Base構造函數調用overrideMeChild尚未完成初始化final int x ,並且該方法獲取了錯誤的值。 這幾乎肯定會導致錯誤和錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM