2013-03-07 89 views
5

我在Fortran 2003中編寫了一些代碼,它使用稀疏矩陣做了很多線性代數。我試圖利用新標準的一些更抽象的特性,所以我有更簡單的程序,沒有太多重複的代碼。Fortran 2003中的運行時多態性

我有一個程序solver它需要一個矩陣,一些向量,使用的迭代方法的容差等等。我將一個指針傳遞給一個名爲matvec的程序; matvec是我們用於矩陣向量乘法的子程序。

問題是,有時matvec是一個過程,其中發送到此過程通常的一個以上的額外參數colorlist, color1, color2。我可以想到處理這個問題的幾種方法。

第一個想法:定義兩個不同的抽象接口matvec1matvec2和兩個不同的求解器。這有效,但它意味着重複一些代碼,這正是我想要避免的。

另一個想法:保持同樣的抽象接口matvec,使額外的參數,color1color2可選。這意味着在每個matvec例程中使它們成爲可選項 - 即使它們不是真正可選的,也不適用於它們甚至不被使用的例程。很確定,如果我這樣做,我會下地獄。

我能想到很多其他不太理想的解決方案。我想就此提出一些意見 - 我確定有一些優雅的方式可以做到,但我不確定它是什麼。

回答

5

問題是,每次調用過程時是否必須傳遞附加參數(因爲它們在兩次調用之間發生變化),或者它們可以在某個時間點初始化,然後在函數中使用。在後面的例子中,你可以用一個抽象接口創建一個類,它定義了你的子程序matvec和基本參數。然後,您可以使用更專業的課程擴展該課程,該課程可以容納所需的其他選項。他們仍然必須定義與父類相同的接口(具有相同的參數列表),但是當它們的matvec過程被調用時,它們可以使用存儲在其中的附加值。

對於類似情況,您可以找到一個詳細示例in this answer(查找顯示module rechercheRacine的第二個示例)。

2

不是傳遞過程指針作爲一個明確的說法,你可以把各種matvec程序的通用接口後面:

interface matvec 
    module procedure matvec1, matvec2 
end interface 

然後你solver程序可以只使用通用名稱使用或不使用額外的參數。同樣的方法當然也可以使用巴林特商建議限定solver作爲派生類型與類型結合的程序的方法時,應考慮:

type :: solver 
    real, allocatable :: matrix(:,:), v1(:), v2(:) 
contains 
    procedure, pass :: matvec1 
    procedure, pass :: matvec2 
    generic :: matvec => matvec1, matvec2 
end type 

的主要區別是,這不使用多態,以確定正確的程序來調用,而是虛擬參數的特徵。

我不確定你對程序指針的意圖;如果您希望在運行時更改其目標(或者爲其'未定義'狀態指定一些特殊含義),則指針是唯一的方法,並且所有目標都需要匹配相同的抽象接口。如果你只需要根據參數選擇幾個過程中的一個,那麼你可以利用接口(我的例子)或重載(Bálint的例子)。每種類型的擴展都可以擴展一個繼承的新過程的綁定,或者重載一個繼承的特定綁定。