2014-09-26 69 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