2016-07-24 31 views
1

我想了解繼承了Fortran中是如何工作的,但有下面的代碼困難(對不起,如果這是一個常見問題...):重寫父程序具有相同名稱

module mymod 
    implicit none 

    type Pos 
     integer :: n_ = -1 
    contains 
     procedure :: set => Pos_set 
    endtype 

    type, extends(Pos) :: Vec 
     integer :: x_ = -2 
    contains 
     procedure :: set => Vec_set   !! (1) 
     !! procedure :: set => Vec_set_p !! (2) 
    endtype 

contains 

    subroutine Pos_set(p, n) 
     class(Pos) p 
     integer n 
     p% n_ = n 
    endsubroutine 

    subroutine Vec_set(v, n) 
     class(Vec) v 
     integer n 
     v% n_ = n 
     v% x_ = n * 10 
    endsubroutine 

    subroutine Vec_set_p(p, n) 
     class(Vec) p 
     integer n 
     p% n_ = n 
     p% x_ = n * 10 
    endsubroutine 

end 

program main 
    use mymod 
    implicit none 
    type(Pos) p 
    type(Vec) v 

    call p% set(10) 
    call v% set(20) 

    print *, "p = ", p 
    print *, "v = ", v 
end 

通過以上代碼,gfortran 5.2.1提供了以下錯誤消息:

procedure :: set => Vec_set 
     1 
Error: Dummy argument ‘v’ of ‘set’ at (1) should be named ‘p’ 
as to match the corresponding argument of the overridden procedure 

如果更改的set 到(即,由2替換第1行)的結合,其僅通過第一虛設的名稱是從Vec_set不同爭論,然後程序編譯得很好,並給出了預期的結果。我也收到了ifort-14.0和Oracle Fortran的類似錯誤。

這是否意味着要重寫父類型的過程,我們還需要照顧虛擬參數的名稱嗎? (即,不僅是關於哪個類別的信息,還有變量的名稱?)

+1

Like [this](http://stackoverflow.com/q/29011920)? – francescalus

+0

這是否意味着,因爲Fortran允許類型構造函數與關鍵字參數一起使用(使用任意順序),我們需要保留與大多數父類中使用的名稱相同的名稱?因爲這在其他語言中可能並不常見(我認爲它們通常被認爲是位置參數),所以我覺得它很混亂(如果是這種情況......) – roygvib

+0

是的,對於使用抽象的東西,我的問題看起來像是一個鏈接的重複。非常感謝您指向頁面:) – roygvib

回答

1

這不是一個有良好動機的答案,但是:是的,你需要關心假人的姓名參數。

4.5.7.3中的特定限制(在Fortran 2008中)。正如您已經指出的那樣,您在此處所取代的是類型爲vecpos類型的綁定名稱set。如果擴展類型中的類型綁定過程與父類型中的可訪問類型綁定過程具有相同的綁定名稱,則會發生重寫。

對於壓倒性條件允許,在該部分給出了許多條件。值得注意的是以下兩種:

  • 通過對象的虛擬參數,如果有的話,應通過名稱和位置相應。
  • 按位置對應的虛擬參數應具有相同的名稱和特徵,但傳遞對象虛擬參數的類型除外。

如果在類型綁定過程中沒有pass屬性,則傳遞對象的僞參數是參數列表中的第一個參數。當你的編譯器抱怨時,覆蓋過程已經通過了 - 對象名稱的不同。

這個問題的例子沒有使用多態,所以在某種程度上這裏不需要關心重寫(這個過程可能有不同的綁定名稱)。

對於需要此動態分辨率的多態工作,請確保滿足上述限制條件。正如jlokimlin對傳遞的虛擬參數使用一個相當通用的名稱所評論的那樣,如thisself這很流行,這是在除了奇怪的情況下處理這個問題的簡單方法。

或者,關於重寫的一個關鍵部分是父類型綁定過程是可訪問的。如果兩個派生類型在不同的模塊中聲明並且父類型的綁定過程是私有的,那麼不會發生重寫,並且這些限制不適用。 [當然,父母的綁定名稱只能在其定義模塊中使用,但在許多情況下這可能已足夠。]

+0

非常感謝您的解釋。我一直在閱讀標準中的相關部分,但有一個問題:在這個[page](http://stackoverflow.com/questions/29011920/why-do-the-names-of-overriding-arguments-have-to -match-that-of-the-abstract-int)你解釋了一個'print *,baz%(data = s)'等的例子,但是我從來沒有見過這種語法。那麼你能解釋一下這個語法的含義嗎?這是一種調用類型綁定過程的簡短符號嗎? (一些關鍵詞是好的,然後我會搜索信息)。 – roygvib

+0

這只是標準_keyword_(你確實說過一些「關鍵字就夠了」......)參數傳遞,就好像它是任何其他函數一樣。在很多例子中,你可能會遇到這種情況,其中一些列表末尾的可選參數與一些列表前面的列表一起出現,但更廣泛的參數可以以任意順序在參數列表中傳遞,並僅通過關鍵字與實際參數關聯。 (正如您在查看標準文檔,請參閱12.5等) – francescalus

+0

啊,我明白了......在Fortran中,即使對於位置參數,我們也可以使用基於關鍵字的參數關聯(以任意順序)。 (這是正確的嗎?我已經在某個地方讀過,但從來沒有在我的程序中使用,所以不太確定。)並且在你的解釋中'baz%(data = s)'意味着'baz%eval(data = s)如果寫得更明確? (我最初認爲這是構造函數的某種特殊語法,因爲例程的名字被省略了......) – roygvib