2014-09-26 102 views
-1

我想用另一種類型的類型。但是,我無法編譯它。對我來說很奇怪:select類型的東西在主程序中起作用,但它不適用於類型的子例程。FORTRAN:選擇類型編譯錯誤

module ModBuffer 
    implicit none 
    private 
    type, abstract, public :: Buffer 
    contains 
     procedure, public      :: Constructor 
    endtype Buffer 

    type, extends(Buffer), public :: BufferR 
     real(8), allocatable, public   :: BufData(:,:,:) 
    endtype BufferR 

    type, extends(Buffer), public :: BufferI 
     complex(8), allocatable, public   :: BufData(:,:,:) 
    endtype BufferI 

    contains 

    subroutine Constructor(this, dim1, dim2, dim3) 
     class(Buffer), intent(inout)   :: this 
     integer, intent(in)      :: dim1, dim2, dim3 

     select type(this) 
     type is(BufferR) 
      allocate(this%BufData(dim1, dim2, dim3)) 
     type is(BufferI) 
      allocate(this%BufData(dim1, dim2, dim3)) 
     endselect 
    endsubroutine Constructor 
endmodule ModBuffer 

module ModSystem 
    use ModBuffer 
    implicit none 
    private 
    type, public :: System 
     class(Buffer), allocatable, public :: WF 
    contains 
    endtype System 

    type, extends(System) :: NewSystem 
    contains 
     procedure, public :: Constructor 
    endtype NewSystem 

    contains 

    subroutine Constructor(this, Flag) 
     class(NewSystem), intent(inout) :: this 
     logical, intent(in) :: Flag 

     if(Flag) then 
      allocate(BufferR::this%WF) 
     else 
      allocate(BufferI::this%WF) 
     endif 
     select type(this%WF) 
     type is(BufferR) 
      print *, "Buffer is real." 
     type is(BufferI) 
      print *, "Buffer is complex." 
     endselect 
    endsubroutine Constructor 
endmodule ModSystem 


program test 
    use ModSystem 
    !use Operation 
    class(System), allocatable :: s 

    allocate(NewSystem::s) 
    call s%Constructor(.true.) 
endprogram test 

我在「select type(this%WF)」行中收到了編譯錯誤。但是如果我在主程序中定義了一個Buffer類型並且執行相同的操作,那麼就不會有錯誤。任何建議,使代碼編譯?謝謝。

編輯

感謝您的兩點意見。

地點:

select type(this%WF) 

的錯誤信息是:

error #8253: If selector expression in SELECT TYPE is not a named variable, associate-name=> shall appear. 

請到弗拉基米爾·F公司的答案的解決方案。關鍵是要使用關聯(如果我理解正確)來解決問題。直接使用成員會導致錯誤。我同意francescalus,因爲有更好的方法來重現錯誤。但我不知道什麼時候我得到弗拉基米爾答案。

+2

我都不會選這個個人,但有些人對「不起作用」和「我得到一個錯誤」過敏,卻沒有說明它是如何工作的,以及錯誤是怎樣的。沒有人會爲「真實(8)」投票,儘管這不是一個很好的做法。 – 2014-09-27 08:13:08

+0

與Vladimir F同意我還會補充:有很多代碼,這真的是最簡單/最普遍的問題嗎?你說這個修改是有效的:那個修改是什麼?確切的錯誤信息也很有用:我們希望在其他項目中遇到同樣問題的人員能夠找到答案。對於知道答案的人來說,這也是一個有用的提示。 – francescalus 2014-09-27 08:46:52

+0

@VladimirF您能否詳細解釋一下「沒有人會爲真實的(8)投票」。我認爲real(8)是「雙精度」的替代品。而且我知道使用變量來指定「kind」會更好。請告訴我更多關於你的意見。謝謝。 – FortCpp 2014-09-27 18:40:41

回答

3

沒有理由使用指針,只是使用的select type的關聯部分(你沒有寫錯誤信息,但IIRC它是相當的描述):

select type (twf => this%WF) 
+0

太棒了!奇蹟般有效。 – FortCpp 2014-09-27 18:29:08

0

我不知道爲什麼這個話題是投票下來。但我找到了一個解決方案。順便說一句,我在窗戶上使用IVF(我幾個月沒有更新)。

看來我不能在觸發IVF編譯器錯誤的「select type」子句中使用某個類型的成員。但是如果你設置了一個指向成員的指針,那麼一切正常。這是一個有點指向解決問題的指針,並沒有多大意義。

module ModBuffer 
    implicit none 
    private 
    type, abstract, public :: Buffer 
    contains 
     procedure, public      :: Constructor 
    endtype Buffer 

    type, extends(Buffer), public :: BufferR 
     real(8), allocatable, public   :: BufData(:,:,:) 
    endtype BufferR 

    type, extends(Buffer), public :: BufferI 
     complex(8), allocatable, public   :: BufData(:,:,:) 
    endtype BufferI 

    contains 

    subroutine Constructor(this, dim1, dim2, dim3) 
     class(Buffer), intent(inout)   :: this 
     integer, intent(in)      :: dim1, dim2, dim3 

     select type(this) 
     type is(BufferR) 
      allocate(this%BufData(dim1, dim2, dim3)) 
     type is(BufferI) 
      allocate(this%BufData(dim1, dim2, dim3)) 
     endselect 
    endsubroutine Constructor 
endmodule ModBuffer 

module ModSystem 
    use ModBuffer 
    implicit none 
    private 
    type, public :: System 
     class(Buffer), allocatable, public :: WF 
    contains 
    endtype System 

    type, extends(System), public :: NewSystem 
    contains 
     procedure, public :: Constructor 
    endtype NewSystem 

    contains 

    subroutine Constructor(this, Flag) 
     class(NewSystem), intent(inout) :: this 
     logical, intent(in) :: Flag 
     class(Buffer), pointer :: P 

     if(Flag) then 
      allocate(BufferR::this%WF) 
     else 
      allocate(BufferI::this%WF) 
     endif 
     call SetPointer(P, this%WF) 
     select type(P) 
     type is(BufferR) 
      print *, "Buffer is real." 
     type is(BufferI) 
      print *, "Buffer is complex." 
     endselect 
    endsubroutine Constructor 

    subroutine SetPointer(MyP, MyA) 
     class(Buffer), pointer :: MyP 
     class(Buffer), target :: MyA 
     MyP => MyA 
    endsubroutine SetPointer 
endmodule ModSystem 


program test 
    use ModSystem 
    !use Operation 
    class(System), allocatable :: s 

    allocate(NewSystem::s) 
    select type(s) 
    type is(NewSystem) 
     call s%Constructor(.true.) 
    endselect 
endprogram test