2013-09-06 14 views
6

UPDATE: Modificato il codice correggere l'errore, se qualcuno è interessato a come un esempioarray di oggetti estesi in Fortran

Sto cercando di ottenere il blocco di programmazione orientata agli oggetti in Fortran, ma ottenuto alcuni problemi . Qualsiasi aiuto sarà molto apprezzato:

Voglio archiviare i puntatori agli oggetti estesi da una classe astratta in una matrice e quindi chiamare una delle subroutine astratte per questi oggetti. Tuttavia ottengo un errore di compilazione in cui sto cercando di chiamare la 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) 

Ho una classe astratta in Body.f90 con due procedure differite:

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 

Poi ho 'Ho una semplice classe con una matrice puntatore che dovrebbe mantenere diversi oggetti che estende la classe astratta Body, Body_set.f90 (Ho incluso tutte le subroutine utilizzate, ma quella importante è nella parte inferiore):

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 

Parte importante della 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 

risposta

9

L'errore è semplice e molto chiaro. Stai chiamando una subroutine come una funzione. È possibile chiamare una subroutine usando solo call. Probabilmente hai desiderato una funzione nell'interfaccia di definizione per get_mass.

+1

OH bontà! È stato un errore ridicolo da parte mia. Molte grazie! :) – Paul