2017-02-26 6 views
3

親モジュールで使用される(子)モジュールの変数は、親モジュールだけでメインプログラムでアクセス可能であることに気付きました。これは、Fortranのuse文をC/C++のinclude文と明確に区​​別する1つの概念です。以下のプログラムは、この概念を明確に示しています。Fortranのモジュールで使用されるモジュールの場合の変数の範囲

a.f90

module a_mod 
use b_mod 
implicit none 

integer :: a 
end module 

b.f90

module b_mod 
    use c_mod 
    implicit none 

    integer :: b 

end module 

c.f90

module c_mod 
    implicit none 

    integer :: c = 10 

contains 

    subroutine inc_c 
    c = c + 10 
    end subroutine inc_c 
end module 

test.f90

program test 
    use a_mod 
    implicit none 

    call inc_c 
    write(*,*),c 
end program 

私はちょうどa_modを使用してc_modで関数を呼び出すことができています注意してください。依存リストをトラバースしない限り、c_modが利用可能であることを直接観察することはできません。

しかし、複雑なソフトウェアでは、変数が特定の行で使用できるかどうかを簡単に知る方法がありますか(IDEを使用するなど)?

+0

すべてのIDEが異なります。これは本当に答えることはできません。いくつかのIDEはこの機能を提供し、他のIDEは提供しないかもしれません。多くのFortranプログラマはIDEを一切使用していません。 –

+3

Fortranには、「private」、「public」、および「only」を使用して、アクセシビリティのより良いFortranがあります。 –

答えて

2

私の意見では、ブランケットuseステートメントの使用を避けることをお勧めします。特に大型で扱いにくいモジュールの場合は特にそうです。代わりに、のような、onlyキーワードを経て継承するモジュールのエンティティを指定:

program main 
    use a_mod, only : c, inc_c 
    implicit none 

    call inc_c 
    write(*,*) c 
end program main 

これは動作しますが、a_modcinc_cの本当の所有者ではないので、それは混乱です。そのため、あなたは彼らが実際に与える、と宣言しているところからuseエンティティに試してみてください:

program main 
    use c_mod, only : c, inc_c 
    ! ^This has changed 
    implicit none 

    call inc_c 
    write(*,*) c 
end program main 

を今、コードを読んで誰もが、彼らがどこから来た変数やサブルーチンは範囲内にあり、その明確な概念を持っています。

最後に、c_modが実際には存在しないことを認識せずにcを使用するリスクを軽減するという利点があります。これは、特にimplicit noneを使用しない場合の問題です!

1

コメントにVladimir Fが示唆しているように、モジュール内でprivatepublicステートメントを使用してこの問題を解決できます。あなたはこのようなあなたのモジュールを書き換えた場合:この場合

module a_mod 
    use :: b_mod 

    private 
    public :: a 

    integer :: a 
end module 

module b_mod 
    use :: c_mod 

    private 
    public :: b 

    integer :: b 
end module 

module c_mod 
    private 
    public :: c, inc_c 

    integer :: c = 10 
contains 
    subroutine inc_c 
    c = c + 10 
    end subroutine 
end module 

、各モジュールの先頭で声明privateは、モジュール内で宣言された量ははデフォルトではエクスポートされないことを意味します。モジュールusepublicステートメントを追加することで利用可能になる変数とサブルーチンを明示的に宣言する必要があります。代わりに、構文integer, public :: c = 10を使用して1行で行うこともできます。この方法では、c_mod変数がb_modから漏れないようにします。

+0

これは効果的に問題を解決するとは思わない。ポイントは 'b_mod'の' c_mod'の 'c'と' inc_c'を使用することです。エンティティを非公開にすることは、それを防ぎます – Ross

+0

私はあなたがエントリをどこにでも秘密にすることを示唆していません。私はあなたが 'c_mod'で' public 'にすることを提案しています(あなたが 'use :: c_mod'を使うときに*インポートされるように)。しかし、' b_mod'で 'private'と同じ変数をあなたが ':: b_mod'や' use :: a_mod'を使うときにはインポートされません。これは問題を解決すると私は信じています。 – jabirali

+0

私の 'c_mod'のバージョンでは、' public :: c、inc_c'と明示的に言っていますが、あなたのコメントは私が 'private'に設定したと思っていることを示しています。 – jabirali

0

IDEのようにinituitではありませんが、gfortranは、-fdump-fortran-original(または-fdump-parse-tree)オプションを付けて、インポートされたシンボルのリストを出力できます。そうするために、我々は最初の

gfortran -c {c,b,a}.f90 

として*の.modファイルを生成し、その後

gfortran -fdump-fortran-original -c test.f90 

として所望のソースをコンパイルし、我々はこのようなインポートされたシンボルのリストを取得する:

Namespace: A-Z: (UNKNOWN 0) 
procedure name = test 
    symtree: 'a'   || symbol: 'a'    
    type spec : (INTEGER 4) 
    attributes: (VARIABLE IMPLICIT-SAVE USE-ASSOC(a_mod)) 
    symtree: 'a_mod'  || symbol: 'a_mod'   
    type spec : (UNKNOWN 0) 
    attributes: (MODULE USE-ASSOC(a_mod)) 
    symtree: 'b'   || symbol: 'b'    
    type spec : (INTEGER 4) 
    attributes: (VARIABLE IMPLICIT-SAVE USE-ASSOC(b_mod)) 
    symtree: 'b_mod'  || symbol: 'b_mod'   
    type spec : (UNKNOWN 0) 
    attributes: (MODULE USE-ASSOC(b_mod)) 
    symtree: 'c'   || symbol: 'c'    
    type spec : (INTEGER 4) 
    attributes: (VARIABLE IMPLICIT-SAVE USE-ASSOC(c_mod)) 
    symtree: 'c_mod'  || symbol: 'c_mod'   
    type spec : (UNKNOWN 0) 
    attributes: (MODULE USE-ASSOC(c_mod)) 
    symtree: 'inc_c'  || symbol: 'inc_c'        <---   
    type spec : (UNKNOWN 0)            <--- 
    attributes: (PROCEDURE MODULE-PROC USE-ASSOC(c_mod) SUBROUTINE) <--- 
    symtree: 'test'  || symbol: 'test'   
    type spec : (UNKNOWN 0) 
    attributes: (PROGRAM PUBLIC SUBROUTINE) 

(たとえば、矢印の付いた線は、がc_modから利用可能であることを示しています)。onlyというキーワードを添付するようにtest.f90を変更すると、

program test 
    use a_mod, only: inc_c 
    implicit none 

    call inc_c 
end program 

、出力もそれに応じて簡略化されている:

Namespace: A-Z: (UNKNOWN 0) 
procedure name = test 
    symtree: 'a_mod'  || symbol: 'a_mod'   
    type spec : (UNKNOWN 0) 
    attributes: (MODULE USE-ASSOC(a_mod)) 
    symtree: 'inc_c'  || symbol: 'inc_c'   
    type spec : (UNKNOWN 0) 
    attributes: (PROCEDURE MODULE-PROC USE-ASSOC(c_mod) SUBROUTINE) 
    symtree: 'test'  || symbol: 'test'   
    type spec : (UNKNOWN 0) 
    attributes: (PROGRAM PUBLIC SUBROUTINE) 

だから、私はこの目的のためには、このオプションを使用したことがありませんalthogh、それは(本当に必要ならばOPの目的のためにいくつかの使用であるかもしれません)。

関連する問題