代码之家  ›  专栏  ›  技术社区  ›  R. N

gfortran指针过程类型问题

  •  1
  • R. N  · 技术社区  · 7 年前

    我尝试创建一个可以接受不同输入类型的过程,而不使用泛型过程。实际上,(在本例中)我更喜欢手动设置过程指针的目标来定义要使用的过程,而不是一般过程。

    这就是我用下面这个几乎最小的例子所做的。

    module mo
    implicit none
    
    type :: TypeB
        character(len=5) :: info='Hello'
        contains
        procedure,  pass(fd) :: say_hello 
    end type TypeB
    
    type :: TypeA
        character(len=4) :: txt='Hola'
        !type(TypeB) :: Tb
    end type TypeA
    
    type, extends(TypeA) :: TypeC
        character(len=4) :: tt='Hey!'
        type(TypeB) :: Tb
    end type TypeC
    
    type, extends(TypeA) :: TypeD
        character(len=3) :: tt='Ho!'
        character(len=3) :: ti='you'
        !type(TypeB) :: Tb
    end type TypeD
    
    type(TypeC) :: Tc
    type(TypeD) :: Td
    procedure(), pointer :: proc
    class(TypeA), allocatable :: CA
    
    
    contains
    
    subroutine say_hello(fd)
        implicit none
        ! type(TypeB), intent(inout) :: fd
        class(TypeB), intent(inout) :: fd
    
        print *, fd%info
    
    end subroutine say_hello
    
    subroutine procC(fd, args)
        implicit none
        ! class(TypeC), intent(inout) :: fd
        type(TypeC), intent(inout) :: fd
        real :: args
    
        print*, args
        print*, fd%tt
        call fd%Tb%say_hello()
    end subroutine procC
    
    subroutine procD(fd, args)
        implicit none
        ! class(TypeD), intent(inout) :: fd
        type(TypeD), intent(inout) :: fd
        ! class(TypeA), intent(inout) :: fd
        real :: args
    
        print*, args
        print*, fd%tt
        print*, fd%ti
    end subroutine procD
    
    end module mo
    
    
    program p
        use mo
        implicit none
    
        print* , 'START'
        print *, Tc%tb%info
        print *, Tc%txt
        call Tc%Tb%say_hello()
        call procC(Tc, 1.0)
        call procD(Td, 2.0)
        print*, 'OK'
    
        allocate(TypeD :: CA)
        proc =>procD
        call proc(CA, 3.0)
        deallocate(CA)
    
        allocate(TypeC :: CA)
        proc =>procC
        call proc(CA, 4.0)
        deallocate(CA)
    
        print*, 'END'
    
    end program p
    

    在Linux上使用ifort编译时,我得到了预期的结果,但在Windows或Linux上使用gfortran(MinGW 6.2.0)编译时(gfortran 5.5.0和6.4.0),我得到了一些奇怪的结果:

    START
    Hello
    Hola
    Hello
    1.00000000
    Hey!
    Hello
    2.00000000
    Ho!
    you
    OK
    3.00000000
    
    @R
    4.00000000
    
    ÇR@
    END
    

    当我在有分段错误的大程序中使用这种方法时,情况变得更糟了。

    那么,有没有办法避免这些问题呢?这是gfortran的bug吗?还是我误解了什么?

    1 回复  |  直到 7 年前
        1
  •  1
  •   francescalus    7 年前

    你的程序在这里出错了。

    考虑该部分

    proc =>procD
    call proc(CA, 3.0)
    

    我首先要考虑的是

    call procD(CA,3.0)
    

    子程序 procD 将第一个伪参数声明为 type(typeD) .这是一个非多形实体,属于动态和声明类型 typeD .实际参数 CA 主程序的是动态类型的多态实体 键入的 但声明的类型 typeA

    在过程引用中,每个伪参数都必须与与其关联的实际参数类型兼容。这里的情况并非如此:非多形对象仅与声明类型与其自身相同的实体类型兼容。它与多态实体的类型不兼容,而多态实体具有相同的动态类型,但不具有相同的声明类型。

    在工作版本中

    call procD(Td, 2.0)
    

    实际参数 Td 属于声明的类型 键入的 因此是类型兼容的。

    在这里使用带有隐式接口的过程指针会使编译器更难在程序中检测到此错误(不需要这样做)。