2010-11-23 4 views
14

現在、Fortranで構造体コンストラクタをオーバーライドできますか?私は、(Fortran 2003の仕様のように)このような提案の例を見てきました:Fortranで構造体コンストラクタをオーバーライドする方法

module mymod 

    type mytype 
    integer :: x 
    ! Other stuff 
    end type 

    interface mytype 
    module procedure init_mytype 
    end interface 

contains 
    type(mytype) function init_mytype(i) 
    integer, intent(in) :: i 
    if(i > 0) then 
     init_mytype%x = 1 
    else 
     init_mytype%x = 2 
    end if 
    end function 
end 

program test 
    use mymod 
    type(mytype) :: x 
    x = mytype(0) 
end program 

これは、基本的には変数名(例えばエラー冗長による誤差のヒープ生成:PROCEDURE属性を持つ「MYTYPE」紛争の派生属性を(1))。 fortran 2003の例の逐語的なコピーは、同様のエラーを生成します。私はgfortran 4.4、ifort 10.1と11.1でこれを試しましたが、それらはすべて同じエラーを生成します。

私の質問:これはfortran 2003の実装されていない機能ですか?あるいは私はこれを間違って実装していますか?

編集:私はbug reportと、この問題に関してgfortranにannounced patchを見つけました。しかし、私はgcc46の11月のビルドを運と同様のエラーで使用しようとしました。

編集2:上記のコードは、Intel Fortran 12.1.0を使用して動作するように見えます。

答えて

6

私はFortran 2008標準のコピーを参考にしました。これにより、派生型と同じ名前の汎用インターフェースを定義することができます。私のコンパイラ(インテルFortran 11.1)はコードをコンパイルしませんので、Fortran 2003標準の未だ実装されていない機能であることを疑う余地があります。

さらに、プログラムにエラーがあります。あなたの関数宣言:とにかく

type(mytype) function init_mytype(i) 
+0

ありがとうございました。気を散らすエラーのためにお詫び申し上げます、それは急いでしまった例でした。 –

17

Is it currently possible to override the structure constructor in Fortran?

type(mytype) function init_mytype 
    integer, intent(in) :: i 

は、おそらくのように書き換えなければならない機能仕様に存在しない引数の存在と意図を指定しますあなたのアプローチを使用しても、コンストラクタのオーバーライドに関する完全なものではありません。主な理由は、構造コンストラクタ#OOPコンストラクタです。いくつかの類似点がありますが、これはちょっとしたアイデアです。

初期化式で非組み込み関数を使用することはできません。定数、配列、構造体のコンストラクタ、組み込み関数のみを使用することができます。詳細は、Fortran 2003ドラフトの7.1.7初期化式を参照してください。私は完全に

type(mytype) :: x 
x = mytype(0) 

type(mytype) :: x 
x = init_mytype(0) 

と何MYMODモジュール内部インターフェイスのブロックを使用しての全体のポイントがあるとの本当の違いは何であるか理解していないアカウントにその事実を取る

まあ、正直言って違いは、巨大なものです - 最初のやり方は誤解を招きます。この関数はコンストラクタではありません(FortranにはOOPコンストラクタが一切存在しないため)、初期化子です。

  1. メモリ割り当て:主流のOOPコンストラクタで


    を順次二つのことを行うための責任があります。

  2. メンバーの初期化。

異なる言語でクラスをインスタンス化する例をいくつか見てみましょう。 Javaの

MyType mt = new MyType(1); 

非常に重要な事実が隠されている - オブジェクトが実際にクラス型のvaribaleへのポインタであるという事実。

MyType* mt = new MyType(1); 

しかし、両方の言語の一方は、2つのコンストラクタ義務も構文レベルで反映されていることがわかります。C++に相当するものは使用ヒープ割り当てであろう。これはキーワードnew(割り当て)とコンストラクタ名(初期化)の2つの部分で構成されます。 のObjective-C構文では、この事実はさらに強調されています

MyType* mt = [[MyType alloc] init:1]; 

多くの時間は、しかし、あなたは、コンストラクタ呼び出しのいくつかの他のフォームを見ることができます。スタックC++割り当ての場合は、実際に我々はそれを考慮することができないので、誤解を招く恐れがあり、特別な(非常に悪い)構文建設

MyType mt(1); 

を使用しています。

パイソン

mt = MyType(1) 

オブジェクトが実際にポインタと割り当ては最初の場所を取るが(シンタックス・レベルで)隠されているという事実であるという事実の両方。そしてこの方法は... __init__と呼ばれています! O_Oそう誤解を招く。 С++のスタック割り当ては、それと比較して消えます。 =)


とにかく、言語におけるコンストラクタを持つというアイデアは、この方法のいくつかの特別な種類を使用して1文のに割り当て初期化を行う能力を意味します。そして、これが「本当のOOP」なのだと思うなら、私はあなたに悪い知らせがあります。 Even Smalltalkdoesn't have constructors。クラス自体にnewメソッドを持たせるのは単なる規約です(メタクラスのシングルトンオブジェクトです)。 Factory Design Patternは、同じ目標を達成するために他の多くの言語で使用されています。

私は、Fortranのモジュールの概念がModula-2に触発されたことをどこかで読んでいます。 OOP機能はOberon-2からインスピレーションを受けているようです。 Oberon-2にはコンストラクタもありません。しかし、もちろん事前宣言されたプロシージャNEW(FortranのALLOCATEのように、しかしALLOCATEは文です)を使った純粋な割り当てがあります。割り当てが終わると、(実際には)初期化子を呼び出すことができます。これは通常の方法です。特別なものはありません。

だからあなたがオブジェクトを初期化するために、工場のいくつかの並べ替えを使用することができます。これは、シングルトンオブジェクトの代わりに実際にモジュールを使用したことです。それとも、(Java/C#/ ...プログラマ)は、後者がないために普通の関数の代わりにシングルトンオブジェクトのメソッドを使用する方がいいです(モジュールなし - 通常の関数を持たない方法、メソッドのみ)。

また、あなたは代わりに、タイプバインドサブルーチンを使用することができます。 init SUBROUTINEのthis引数のための

MODULE mymod 

    TYPE mytype 
    PRIVATE 
    INTEGER :: x 
    CONTAINS 
    PROCEDURE, PASS :: init 
    END TYPE 

CONTAINS 

    SUBROUTINE init(this, i) 
    CLASS(mytype), INTENT(OUT) :: this 
    INTEGER, INTENT(IN) :: i 

    IF(i > 0) THEN 
     this%x = 1 
    ELSE 
     this%x = 2 
    END IF 
    END SUBROUTINE init 

END 

PROGRAM test 

    USE mymod 

    TYPE(mytype) :: x 

    CALL x%init(1) 

END PROGRAM 

INTENT(OUT)は大丈夫のようです。なぜなら、このメソッドは割り当ての直後に1回だけ呼び出されるからです。この仮定が間違っていないことを制御することは良い考えです。 mytypeにいくつかのブールフラグLOGICAL :: initedを追加するには、それは.false.で、最初の初期化時に.true.に設定するかどうかを確認し、再初期化への試みに何かを行います。私は間違いなくGoogle Groupsでそれについてのいくつかのスレッドを覚えています...私はそれを見つけることができません。

+2

清算していただきありがとうございます。私はそれが純粋なOOPの意味でのコンストラクタではなく、同様の代替アプローチが同じことのほとんどを達成することを理解しています。むしろ、これはp445(C.1.6)のほぼそのままの例であり、作者は仕様作業草案の1つで「構造コンストラクタ」と呼ぶことにしました。そのようなオーバーライドが現在のfortranの一般的な実装で可能かどうか疑問に思った。しかし、私は心にあなたのアドバイスを取る、もう一度ありがとう。 –

関連する問題