简体   繁体   中英

Array of extended objects in Fortran

UPDATE : Modified the code correcting the mistake, if anyone is interested in it as an example

I'm trying to get the hang of OOP in Fortran, but got some problems. Any help will be highly appreciated:

I want to store pointers to objects extended by an abstract class in an array and then call one of the abstract subroutines for these objects. However I get an compilation error where I'm trying to call the subroutine:

src/Body_set.f90(74): error #6553: A function reference is invoking a subroutine subprogram.   [GET_MASS]
        write(*,*) "Body ", i, " - mass: ", b%get_mass()
----------------------------------------------^
src/Body_set.f90(74): error #6402: prPromoteSym : Illegal KIND & CLASS mix   [GET_MASS]
        write(*,*) "Body ", i, " - mass: ", b%get_mass()
----------------------------------------------^
src/Body_set.f90(74): error #7021: Name invalid in this context   [GET_MASS]
        write(*,*) "Body ", i, " - mass: ", b%get_mass()
----------------------------------------------^
compilation aborted for src/Body_set.f90 (code 1)

I've got a abstract class in Body.f90 with two deferred procedures:

module Body_module
   implicit none
   private

   type, public, abstract :: Body
      private
   contains
      procedure(get_mass), deferred :: get_mass
      procedure(set_mass), deferred :: set_mass
   end type Body

   abstract interface
      function get_mass(self) result(m)
         import Body
         class(Body), intent(in)    :: self
         double precision m
      end function

      subroutine set_mass(self, m)
         import Body
         class(Body) :: self
         double precision m
      end subroutine
   end interface

end module Body_module

Then I've got a simple class with an pointer array that should keep different objects that extends the abstract Body class, Body_set.f90 (I've included all used subroutines, but the important one is at the bottom):

module Body_set_module
   use Body_module

   implicit none
   private

   type, public :: Body_container
      class(Body), pointer :: obj
   end type Body_container

   type, public :: Body_set
      private
      integer :: num_bodies
      type(Body_container), allocatable, dimension(:) :: bodies
   contains
      procedure :: set_body
      procedure :: get_body
      procedure :: get_num_bodies
      procedure :: print_summary
      final :: destructor
   end type Body_set

   interface Body_set
      procedure constructor
   end interface Body_set

contains

  !Object contructor
  function constructor(num_bodies) result(self)
     class(body_set),pointer :: self
     integer :: num_bodies

     allocate(self)
     self%num_bodies = num_bodies
     allocate(self%bodies(num_bodies))
  end function constructor

  !Returns number of bodies stored
  function get_num_bodies(self) result(num_bodies)
     class(Body_set), intent(in)  :: self
     integer                      :: num_bodies

     num_bodies = self%num_bodies
  end function get_num_bodies

  !Set element `i` to point to `new_body`
  subroutine set_body(self, new_body, i)
     class(body_set),    intent(inout) :: self
     class(Body), target, intent(in)    :: new_body
     integer,    intent(in) :: i

     self%bodies(i)%obj => new_body
  end subroutine set_body

   !Return pointer to body `i`
   function get_body(self, i) result(the_body)
     class(Body_set), intent(in)  :: self
     integer,         intent(in)  :: i
     class(Body),     pointer     :: the_body

     the_body => self%bodies(i)%obj
   end function get_body

Important part of Body_set.f90 :

  !Print a summary of all bodies
  subroutine print_summary(self)
     class(body_set),  intent(in) :: self
     integer :: i
     class(Body),  pointer :: b

     write(*,*) "Summary of ", self%num_bodies, " bodies:"
     do i=1,self%get_num_bodies()
        b => self%get_body(i)
        write(*,*) "Body ", i, " - mass: ", b%get_mass()
     end do
  end subroutine print_summary


   subroutine destructor(self)
     type(body_set), intent(in) :: self
   end subroutine

end module Body_set_module

The error is simple and very clear. You are calling a subroutine as a function. You can call a subroutine only using call . You probably wanted a function in the defining interface for get_mass .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM