如何将子例程名称作为Fortran类中的参数传递 [英] How to pass subroutine names as arguments in Fortran classes

查看:253
本文介绍了如何将子例程名称作为Fortran类中的参数传递的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在Fortran中将子例程名称作为参数传递? 我们学习了如何在Fortran中将子例程名称作为参数传递。我们如何在类结构中做到这一点?

接下来的代码使用GNU Fortran(GCC)5.1.0产生以下编译错误:

  gfortran -Wall -Wextra -Wconversion -Og -pedantic -fcheck = bounds -fmax-errors = 5 class_pass.f08 
myClass.f08:44:30:

class(test),target :: me
1
错误:在定义之前使用(1)处的派生类型'test'
myClass.f08:9:21:

procedure,public :: action => action_sub
1
错误:在(1)
myClass.f08:40:36:

类中的'action_sub'的非多态传递对象伪参数测试),target :: me
1
错误:(1)处的CLASS变量'me'必须是虚拟的,可分配的或指针
(null):0:被以前的错误困惑, out

主程序如下。它包含一个用于诊断的例程 check


$ b

  include'myClass .f08'
程序class_pass

使用myClass
隐式无

类型(测试):: myTest

call myTest %check()
call myTest%action(square_sub)

end program class_pass

模块:

  module myClass 

隐式无

type :: test
real :: x,y
包含
private
procedure,public :: action => action_sub
procedure,public :: square => square_sub
procedure,public :: double => double_sub
过程,public :: check => check_sub
结束类型测试

private :: action_sub
private :: square_sub
private :: double_sub
private :: check_sub

包含

子程序square_sub(me)
class(test),target :: me
me%y = me%x ** 2
end子程序square_sub

子程序double_sub(me)
class(test),target :: me
me%y = me%x * 2
end subroutine double_sub

子程序check_sub(me)
class(test),target :: me $ b $ me%x = 5.0
call double_sub(me)
print *,'x = ',me%x,',y =',me%y
结束子程序check_sub

子程序action_sub(子)
class(test),target :: me

接口mySub
子例程sub(me)
class(test),target :: me
end subroutine su b
end interface mySub

call sub(me)
print *,'x =',me%x'',y =',me%y

结束子程序action_sub

结束模块myClass

非常感谢@ vladimir F为原始解决方案和技巧。 您的错误是由于您的过程中缺少参数 action_sub 和其他一些小事情。这个过程通过

  procedure,public :: action =>绑定到派生类型。 action_sub 

,默认情况下,多态类变量作为第一个参数传递给 action_sub 。您已在其他类型的绑定过程中正确说明了这一点,但在此过程中没有这样做。您还需要将接口块中的派生类型导入到 action_sub 中,以便在那里使用该类型。这个过程的修改版本可以让你的模块正确编译:

 子程序action_sub(me,sub)
class (test),target :: me

interface mySub
子例程sub(me)
import test
class(test),target :: me
end子程序sub
end interface mySub

call sub(me)
print *,'x =',me%x'',y =',me%y

结束子程序action_sub

接下来,在你的主程序中: >

  call myTest%action(square_sub)

以便引用 square_sub 这里您需要在您的模块中公开该过程。从模块过程中删除 private 属性后,代码将编译并运行:

  x = 5.00000000,y = 10.0000000 
x = 5.00000000,y = 25.0000000


In How to pass subroutine names as arguments in Fortran? we learned how to pass subroutine names as arguments in Fortran. How can we do this inside a class structure?

The ensuing code produces the following compilation error using GNU Fortran (GCC) 5.1.0:

gfortran  -Wall -Wextra -Wconversion -Og -pedantic -fcheck=bounds -fmax-errors=5 class_pass.f08 
myClass.f08:44:30:

                 class ( test ), target :: me
                              1
Error: Derived type ‘test’ at (1) is being used before it is defined
myClass.f08:9:21:

             procedure, public :: action => action_sub
                     1
Error: Non-polymorphic passed-object dummy argument of ‘action_sub’ at (1)
myClass.f08:40:36:

         class ( test ), target :: me
                                    1
Error: CLASS variable ‘me’ at (1) must be dummy, allocatable or pointer
(null):0: confused by earlier errors, bailing out

The main routine follows. It includes a routine check used as a diagnostic.

include 'myClass.f08'
program class_pass

    use myClass
    implicit none

    type ( test ) :: myTest

        call myTest % check ()
        call myTest % action ( square_sub )

end program class_pass

The module:

module myClass

    implicit none

    type     :: test
        real :: x, y
        contains
            private
            procedure, public :: action => action_sub
            procedure, public :: square => square_sub
            procedure, public :: double => double_sub
            procedure, public :: check  => check_sub
    end type test

    private :: action_sub
    private :: square_sub
    private :: double_sub
    private :: check_sub

contains

    subroutine square_sub ( me )
        class ( test ), target :: me
            me % y = me % x ** 2
    end subroutine square_sub

    subroutine double_sub ( me )
        class ( test ), target :: me
            me % y = me % x * 2
    end subroutine double_sub

    subroutine check_sub ( me )
        class ( test ), target :: me
            me % x = 5.0
            call double_sub ( me )
            print *, 'x = ', me % x, ', y = ', me % y
    end subroutine check_sub

    subroutine action_sub ( sub )
        class ( test ), target :: me

        interface mySub
            subroutine sub ( me )
                class ( test ), target :: me
            end subroutine sub
        end interface mySub

            call sub ( me )
            print *, 'x = ', me % x, ', y = ', me % y

    end subroutine action_sub

end module myClass

Many thanks to @Vladimir F for the original solution and tips.

解决方案

Your errors are due to missing parameters in your procedure action_sub and a few other minor things. This procedure is bound to your derived type via

procedure, public :: action => action_sub

and by default the polymorphic class variable is passed as the first argument to action_sub. You have correctly accounted for this in your other type bound procedures, but are missing it in this procedure. You also need to import the derived type in the interface block within action_sub in order to use the type there. This modified version of just that procedure allows your module to compile properly:

subroutine action_sub ( me, sub )
    class ( test ), target :: me

    interface mySub
        subroutine sub ( me )
            import test
            class ( test ), target :: me
        end subroutine sub
    end interface mySub

        call sub ( me )
        print *, 'x = ', me % x, ', y = ', me % y

end subroutine action_sub

next, in your main program where you do:

call myTest % action ( square_sub )

in order to reference square_sub here you need to make the procedure public in your module. Once you remove the private attribute from the module procedure your code compiles and runs:

 x =    5.00000000     , y =    10.0000000
 x =    5.00000000     , y =    25.0000000

这篇关于如何将子例程名称作为Fortran类中的参数传递的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆