class - Fortran 指针多态性

标签 class pointers fortran polymorphism

我正在尝试使用指针在对象之间创建链接。使用 Fortran,下面是代码片段:

 module base_pars_module
   type,abstract,public :: base_pars
   end type
 end module 
 module test_parameters_module
   use base_pars_module
   type, extends(base_pars) :: test_pars
     contains 
     procedure :: whoami
   end type
   contains
   function whoami(this) result(iostat)
     class( test_pars) :: this
     write(*,*) 'i am a derived type child of base_pars'
   end type
 end module
 module base_mask_module
   use base_pars module
     type, abstract , public :: base_mask
     class(base_pars),pointer :: parameters
   end type
end module
module test_mask_module
  use base_mask_module
  implicit none
  type, extends(base_mask) :: test_mask
  end type
end module
program driver
type(test_pars) , target :: par_Test
type(test_mask) :: mask_test
  iostat= par_test%whoami()
  mask_test%parameters=>par_test
  iostat=mask_test%parameters%whoami()
end program
base_mask_module 处的

parameters 是一个 base_pars 类的指针。我想使用此指针来引用 par_test 对象,该对象是扩展 base_pars 类型的 test_pars 类型。所以指针和目标具有相同的类。但是当我编译它时,它给出了一个错误:

 driver.f90:17.37:

iostat=mask_test%parameters%whoami()
                                  1
Error: 'whoami' at (1) is not a member of the 'base_pars' structure

这是一个错误还是我做错了什么?

最佳答案

当您具有这样的多态性时,需要考虑对象的两件事:其动态类型和其声明类型。 test_mask (base_mask) 的 parameters 组件声明为

class(base_pars),pointer :: parameters

因此,此类组件已声明类型 base_pars

来指针赋值

mask_test%parameters=>par_test

mask_test%parameters 的动态类型与 par_test 相同:test_pars。不过,它是声明类型 base_pars 的,当我们关心它的组件和绑定(bind)时,声明类型很重要。 base_pars 确实没有 whoami

那么,您需要声明类型为 par_test 的东西。无需更改派生类型的定义,您可以使用select type 构造来完成此操作。

select type (pars => mask_test%parameters)
class is (par_test)
  iostat=pars%whoami()  ! pars of declared type par_test associated with mask_test%parameters
end select

也就是说,使用这种方法事情很快就会变得非常乏味。始终使用选择类型,区分众多扩展类型,将是一个相当大的束缚。另一种方法是确保声明的类型 base_pars 具有绑定(bind) whoami。我们没有像上面那样改变主程序,而是改变模块base_pars_module:

module base_par_modules
  implicit none  ! Encourage good practice

  type,abstract,public :: base_pars
   contains
    procedure(whoami_if), deferred :: whoami
  end type

  interface
    integer function whoami_if(this)
      import base_pars    ! Recall we're in a different scope from the module
      class(base_pars) this
    end function
  end interface

end module

因此,我们在 base_pars 中有一个延迟绑定(bind),稍后会被扩展类型 test_pars 中的绑定(bind)覆盖。主程序中的mask_test%parameters%whoami()是有效的,调用的函数是动态类型的parameters提供的函数。

这里的两种方法都解决了参数的声明类型的绑定(bind)问题。哪种最适合您的实际问题取决于您的整体设计。

如果您知道您的类型层次结构都与基本类型有足够的共同点(也就是说,所有类型都将提供 whoami 绑定(bind)),那么采用第二种方法是有意义的。当您遇到奇怪的特殊情况时,请使用第一种方法,我建议这种情况应该很少见。

关于class - Fortran 指针多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31220961/

相关文章:

fortran - Fortran 77 中的 IEEE_UNDERFLOW_FLAG IEEE_DENORMAL

c++ - 为什么我收到 "no matching function"错误?

scala - 在 SPARK REPL 上出现错误(对 A 的引用不明确)并且在 Intellij 和 Scala REPL 中工作正常?

class - 类图如何转换为代码?

c - 有没有办法 malloc 一个数组大小为 10 的整数指针并返回它的值?

Javascript:将函数指针放入对象中?

Ruby:继承使用类变量的代码

c++ - 指向 C++ 类元素的指针

fortran - 作为函数参数的内在函数

linux - linux pgf90 编译器第二次调用子程序时出现段错误