Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Inheritance 无法使用继承将数据和过程多态性混合使用_Inheritance_Fortran_Polymorphism - Fatal编程技术网

Inheritance 无法使用继承将数据和过程多态性混合使用

Inheritance 无法使用继承将数据和过程多态性混合使用,inheritance,fortran,polymorphism,Inheritance,Fortran,Polymorphism,我最近尝试在代码中引入一些新的fortran 2003特性。基本上,我想混合使用数据和过程多态性。阅读了关于这些概念的基本教程(Fortran 2003中的面向对象编程) 第1部分:代码重用性:和 Fortran 2003中的面向对象编程 第2部分:数据多态性)我试图让我的基本概念发挥作用 我的想法是我有一个基本类型交互,它有一个名称和一些类型绑定的过程。然后我有一些特定的交互,比如smallso2inv,它们通过一些参数扩展交互类型,并覆盖基本类型的类型绑定过程。现在我想传递基本类型的init

我最近尝试在代码中引入一些新的fortran 2003特性。基本上,我想混合使用数据和过程多态性。阅读了关于这些概念的基本教程(Fortran 2003中的面向对象编程) 第1部分:代码重用性:和 Fortran 2003中的面向对象编程 第2部分:数据多态性)我试图让我的基本概念发挥作用

我的想法是我有一个基本类型
交互
,它有一个名称和一些类型绑定的过程。然后我有一些特定的交互,比如
smallso2inv
,它们通过一些参数扩展交互类型,并覆盖基本类型的类型绑定过程。现在我想传递基本类型的initialize方法一个交互名称,如

call interaction%initialize("smallso2inv")
然后,内部指针
specInteraction
应该指向类型
smallso2inv
。现在使用时

call interaction%readInit() 
我希望调用smallso2inv类型的readInit例程。这将使用计算所需的参数填充
smallso2inv
类型

下面是我的交互模块的一个小的工作示例,它具有上述类型和我当前的实现:

module mod_interaction
implicit none
  public
  type interaction
   character*80 :: name                                                     
   class(interaction), pointer :: specInteraction => null()
   procedure, pass(this) :: readInit
   procedure, pass(this) :: readUpdate
   procedure, pass(this) :: compute
   procedure, pass(this) :: addToHamiltonian
   procedure, pass(this) :: updateParameter
  end type interaction

  type, extends(interaction) :: smallso2inv                                                                                          
   double precision :: uvalue, j1value, j2value
   double precision :: uincr, j1incr, j2incr
   contains
   procedure, pass(this) :: setup => smallso2inv_initialize
   procedure, pass(this) :: readInit => smallso2inv_readInit
   procedure, pass(this) :: readUpdate => smallso2inv_readUpdate
   procedure, pass(this) :: compute => smallso2inv_compute
   procedure, pass(this) :: addToHamiltonian => smallso2inv_addToHamiltonian
   procedure, pass(this) :: updateParameter => smallso2inv_updateParameter
  end type smallso2inv

contains

 subroutine initialize(this,name)              
   implicit none               
   type(interaction) :: this
   character*80 :: name
   class(interaction), allocatable, target :: thisInteraction
   !
   select case(name)
    case('smallSO2inv')
     allocate(smallso2inv::thisInteraction)
     call thisInteraction%setup()
     this%specInteraction => thisInteraction
   end select

 end subroutine initialize

 subroutine smallso2inv_initialize(this)
  !
  class(smallso2inv) :: this
  !              
  this%uvalue = 0.0d0
  this%j1value = 0.0d0
  this%j2value = 0.0d0
  print*, "hallo smallso2inv init"              
 end subroutine smallso2inv_initialize

 subroutine readInit (this)
  class(interaction) :: this
  character*80 :: name        
  call this%specInteraction%readInit()             
 end subroutine readInit

 subroutine smallso2inv_readInit(this)
  !
   class(smallso2inv) :: this
   !
   print*, "hello smallso2inv readInit"
   !
  end subroutine smallso2inv_readInit

end module mod_interaction
我现在在使用ifort 15.0.0时遇到了两个错误

error #6437: A subroutine or function is calling itself recursively.   [READINIT]

call this%specInteraction%readInit()

error #6460: This is not a field name that is defined in the encompassing structure.   [SETUP]

call thisInteraction%setup()
我的实现似乎试图从基本的
交互
类型调用子例程,而不是使用
smallso2inv
类型。是否有一种方法可以解决此问题,而无需转到
readInit
子例程中的case-type开关?我认为这应该是可能的,但不知何故,我认为我混淆了指针和变量的用法,因为我对多态上下文中指针的理解仍然有限。
提前感谢你的帮助

可能会有更多错误,但这是报告的错误:

初始化调用本身。它使用不同的对象实例调用它并不重要。它必须是递归的

 recursive subroutine readInit (this)
  class(interaction) :: this 
  call this%specInteraction%readInit()             
 end subroutine readInit
另一个错误是初始化错误。您需要使用
select type
typeguard。在<代码>类型中,区域可以考虑<代码>此交互< /代码>具有新的非多态类型。您也可以改用
类is
。我不确定这是否是一个明智的设计选择。我个人会选择两个单独的过程,可能是重载类型名的函数

 subroutine initialize(this,name)              
      ...
   select case(name)
    case('smallSO2inv')
     allocate(smallso2inv::thisInteraction)
     select case (thisInteraction)
       type is (smallso2inv)
         call thisInteraction%setup()
         this%specInteraction => thisInteraction
     end type
   end select

 end subroutine initialize

请注意,
字符*n
表示法非常过时,如果没有任何特殊的用户定义的赋值,没有理由使用
=0.0d0
而不是简单的
=0

递归抱怨(在我看来)是一个编译器错误[1]。在一般情况下,编译器在编译时无法知道readInit绑定将分派到哪个特定过程,递归调用的限制是一个执行概念(即在运行时)。简单的解决方法是让步并添加递归属性

您只能访问声明的对象类型的绑定(和组件)。一个选项是用所需类型声明“临时”对象(注意,您有对象生存期问题,因此我将临时对象设为下面的指针),或者您可以使用Vladimir F建议的类似于结构构造函数的函数。对于简单构造,函数方法是典型的,但是,如果构造过程需要传回的不仅仅是构造对象(故障标志或类似),那么使用局部临时对象可能更合适

subroutine initialize(this,name)              
  implicit none               
  type(interaction) :: this
  character(80) :: name
  !
  select case(name)
   case('smallSO2inv')
    block
      ! Local pointer of the required type.
      type(smallso2inv), pointer :: thisInteraction
      ! Allocate an object of that type and point the pointer at it.
      allocate(thisInteraction)
      ! Initialize the object.
      call thisInteraction%setup()
      ! Save the pointer.
      this%specInteraction => thisInteraction
    end block
  end select
 ...
这可能更像是一个样式问题,但是在上面,通过
设置
绑定调用
smallso2inv\u initialize
过程没有实际意义,因为具有绑定的对象不是多态的(因此其动态类型和声明的类型是相同的)-您可以直接调用该过程

您还应该考虑组件和临时是否需要指针——如果组件未被用作引用,则使它们都可分配(使用MOVELYOLLC从临时转移到多态性组件)。


[1] :与此类似。

实际上,此稍微更改的设置起作用(仅供浏览此问题的用户参考):


事实证明,Vladimir F answer对使我的
初始化
例程工作非常有帮助,而IanH answer对使
readInit
例程工作非常有帮助。对此解决方案的一些评论。这完全适用于ifort 15.0.0其他尚未测试的编译器
specInteraction
必须是一个指针,如在ifort 15.0.0中,类型interaction
不能包含相同类型的可分配类(未实现的功能)。就像IanH所说的那样,
readInit
必须是递归的,尽管在运行时调用了类型为
smallso2inv
的正确对象,但编译器在编译时不知道它的类型。这也是类型绑定过程重载在这里很重要的原因,因为每个被调用的过程在编译时也必须在基类
交互中找到。感谢你们两位的大力帮助。

不要单独使用标签
fortran2003
。它的订户非常少。通过阅读您的帖子,没有什么特别针对f2003的东西不在f2008中,所以我重新标记为
fortran
谢谢您的评论。我会在以后的帖子里解释。我不明白你的答案。我需要有
类(交互)::这个
,因为传递的对象来自这个类型。我的想法是使用
这个%specInteraction
来访问适当的基类型扩展(在本例中是smallso2inv)。请注意,没有子例程设置为
过程,pass(this)::setup=>smallso2inv\u initialize
。我认为编译器忽略了分配(smallso2inv::thisInteraction)
这个%specInteraction=>thisInteraction
并坚持基本类型
module mod_interaction
implicit none
  public
  type interaction
   character*80 :: name                                                  
   class(interaction), pointer :: specInteraction => null()
   procedure, pass(this) :: readInit
   procedure, pass(this) :: readUpdate
   procedure, pass(this) :: compute
   procedure, pass(this) :: addToHamiltonian
   procedure, pass(this) :: updateParameter
  end type interaction

  type, extends(interaction) :: smallso2inv                                                                                          
   double precision :: uvalue, j1value, j2value
   double precision :: uincr, j1incr, j2incr
   contains
   procedure, pass(this) :: initialize => smallso2inv_initialize
   procedure, pass(this) :: readInit => smallso2inv_readInit
   procedure, pass(this) :: readUpdate => smallso2inv_readUpdate
   procedure, pass(this) :: compute => smallso2inv_compute
   procedure, pass(this) :: addToHamiltonian => smallso2inv_addToHamiltonian
   procedure, pass(this) :: updateParameter => smallso2inv_updateParameter
  end type smallso2inv

contains

  subroutine initialize(this,name)
    !
    implicit none
    !
    type(interaction) :: this
    character*80 :: name
    class(interaction),allocatable, target :: thisInteraction
    !
    this%name = name
    select case(name)
    case('smallSO2inv')
       allocate(smallso2inv::thisInteraction)
       select type (thisInteraction)
       type is (smallso2inv)
          call thisInteraction%initialize()
          this%specInteraction => thisInteraction
       end select
    end select
    !           
    !
  end subroutine initialize

 subroutine smallso2inv_initialize(this)
  !
  class(smallso2inv) :: this
  !              
  this%uvalue = 0.0d0
  this%j1value = 0.0d0
  this%j2value = 0.0d0
  print*, "hallo smallso2inv init"              
 end subroutine smallso2inv_initialize

  recursive subroutine readInit (this)
    class(interaction) :: this
    class(interaction), allocatable :: thisInteraction
    character*80 :: name
    !
    call this%specInteraction%readInit()
    print*, "name=",this%name
    !
  end subroutine readInit

 subroutine smallso2inv_readInit(this)
  !
   class(smallso2inv) :: this
   !
   print*, "hello smallso2inv readInit"
   print*, "uvalue=",this%uvalue
   !
  end subroutine smallso2inv_readInit

end module mod_interaction