2015-04-21 16 views
6

Tôi là người mới bắt đầu trong OOP với Fortran và tôi đang cố viết một chương trình với các thủ tục xử lý các biến đa hình làm đối số. Mặc dù mã ban đầu của tôi phức tạp hơn nhiều (nhiều thủ tục, một số kiểu có nguồn gốc ...), tôi có thể cô lập một ví dụ đơn giản về vấn đề của tôi, nói: Tôi có một thủ tục sao chép một biến đa hình và hơi sửa đổi bản sao này.Đa hình Fortran, chức năng và phân bổ

tôi đã có thể viết thành công chương trình thử nghiệm của tôi bằng cách sử dụng chương trình con :

MODULE my_module 

type :: my_type 
    real :: data 
endtype my_type 

type, extends(my_type) :: my_derived_type 
end type my_derived_type 

CONTAINS 

subroutine sub_copy(old,new) 
implicit none 
class(my_type), intent(in) :: old 
class(my_type), allocatable, intent(out) :: new 
allocate(new, source = old) 
new%data = new%data + 1 
end subroutine sub_copy 

END MODULE my_module 

PROGRAM my_prog 
use my_module 
implicit none 
type(my_derived_type) :: x 
class(my_type), allocatable :: y 

x%data = 1.0 
call sub_copy(x,y) 
print*,y%data 
deallocate(y) 

END PROGRAM my_prog 

này thực hiện độc đáo cả về kết quả mong đợi và việc phân bổ bộ nhớ/deallocation.

Tuy nhiên, tôi đã đấu tranh cho những ngày cố gắng làm việc chức năng Fortran sẽ thực hiện cùng một công việc.

Dường như một chức năng được xác định theo một cách tương tự như các chương trình con (xem ở đây sau) không thể được sử dụng đơn giản là

y = fun_copy(x) 

và trình biên dịch gfortran tôi (v5.0.0) than phiền:

Error: Assignment to an allocatable polymorphic variable at (1) is not yet supported 

Tôi đã đọc ở đây và ở đó thực sự chuyển nhượng như vậy không được hỗ trợ bởi trình biên dịch của tôi. Chờ đợi cho điều đó, tôi đã cố gắng để làm việc đó xung quanh bằng cách xác định toán tử gán của riêng tôi (=). Các mã sau đây hoạt động:

MODULE my_module 

type :: my_type 
    real :: data 
endtype my_type 

type, extends(my_type) :: my_derived_type 
end type my_derived_type 

interface assignment(=) 
    module procedure myassign 
end interface 

CONTAINS 

function fun_copy(old) result(new) 
implicit none 
class(my_type), intent(in) :: old 
class(my_type), allocatable :: new 
allocate(new, source = old) 
new%data = new%data + 1 
end function fun_copy 

subroutine myassign(new,old) 
class(my_type), intent(in) :: old 
class(my_type), allocatable, intent(out) :: new 
allocate(new, source=old) 
end subroutine 

END MODULE my_module 

PROGRAM my_prog 
use my_module 
implicit none 
type(my_derived_type) :: x 
class(my_type), allocatable :: y 

x%data = 1.0 
y = fun_copy(x) 
print*,y%data 
deallocate(y) 

END PROGRAM my_prog 

Nó hoạt động theo nghĩa là trên thực tế, một bản sao của x được tạo ra như y. Tuy nhiên, kiểm tra ngân sách bộ nhớ của chương trình thử nghiệm đơn giản này (tôi sử dụng phần mềm Instrument trên OS X), có vẻ như một số bộ nhớ không được phân phối trước khi kết thúc. Tôi nghi ngờ rằng chức năng sao chép và phân bổ chương trình con cả cấp phát bộ nhớ và tôi chỉ miễn phí một lần xuất hiện, để lại một lần được phân bổ.

Vì tôi dự định sử dụng một số lần thường xuyên như vậy trong một mã phức tạp hơn nhiều, tôi thực sự lo ngại về phân bổ bộ nhớ/deallocation. Tất nhiên, tôi có thể sử dụng phiên bản chương trình chương trình con của chương trình, nhưng nếu có cách nào, tôi thích phiên bản chức năng.

Có cách nào để giải quyết vấn đề như vậy không?

+0

Trong ví dụ chức năng của bạn, bạn có nghĩa là 'y = fun_copy (x)', tôi đoán vậy. Như một cách giải quyết khác 'cấp phát (y, source = fun_copy (x))', nhưng điều này không hấp dẫn. Nó sẽ là thú vị để xem liệu điều tương tự vẫn tồn tại, mặc dù. – francescalus

+0

@francescalus Vâng, tôi có nghĩa là 'y = fun_copy (x)'. Tôi đã chỉnh sửa bài đăng gốc và sửa lại. Ngoài ra, tôi vừa thử cách giải quyết của bạn và vấn đề phân bổ bộ nhớ/deallocation vẫn tồn tại. Không có thay đổi nào xa như tôi có thể nói. – Reno

+0

Vâng, tôi không (chưa?) Biết câu trả lời, nhưng tôi cho rằng chúng ta có thể loại trừ sự phân công được xác định là vấn đề. – francescalus

Trả lời

0

này nghe có vẻ giống như một câu hỏi tôi đã có một thời gian trở lại về chức năng vs chương trình con:

fortran operator overloading: function or subroutine

Tôi nghĩ rằng đó là một loại thương mại-off giữa việc sử dụng một chương trình con, cho phép phân bổ và deallocation, và sử dụng một hàm chỉ có thể phân bổ. Tôi sẽ đề nghị rằng, nếu các cấu trúc dữ liệu lớn, các hàm có thể tránh được cho việc sử dụng này và dính vào các chương trình con.

1

Bạn đã thử sử dụng con trỏ chưa?

module my_module 

     implicit none 

     type :: my_type 
      real :: data 
     contains 
      procedure    :: sub_copy 
      procedure    :: fun_copy_ptr 
      procedure    :: fun_copy_alloc 
      procedure, pass (this) :: my_assign 
      generic    :: assignment(=) => my_assign 
     end type my_type 

     type, extends(my_type) :: my_derived_type 
     end type my_derived_type 

    contains 

     subroutine sub_copy(this, new) 
      class(my_type), intent (in)    :: this 
      class(my_type), allocatable, intent (out) :: new 

      allocate(new, source=this) 
      new%data = new%data + 1 

     end subroutine sub_copy 

     function fun_copy_alloc(this) result (new) 
      class(my_type), intent(in) :: this 
      class(my_type), allocatable :: new 

      allocate(new, source=this) 
      new%data = new%data + 1.0 

     end function fun_copy_alloc 

     function fun_copy_ptr(this) result (new) 
      class(my_type), intent(in) :: this 
      class(my_type), pointer :: new 

      allocate(new, source=this) 
      new%data = new%data + 1.0 

     end function fun_copy_ptr 

     subroutine my_assign(new, this) 
      class(my_type), intent(in)    :: this 
      class(my_type), allocatable, intent(out) :: new 

      allocate(new, source=this) 

     end subroutine 

    end module my_module 

    program my_prog 

     use my_module, only: & 
      my_type, & 
      my_derived_type 

     implicit none 
     type(my_derived_type)  :: x 
     class(my_type), allocatable :: y 
     class(my_type), pointer  :: y_ptr => null() 

     x%data = 1.0 

     ! Case 1 
     call x%sub_copy(y) 
     print *, y%data 
     deallocate(y) 

     ! Case 2 
     y_ptr => x%fun_copy_ptr() 
     print *, y_ptr%data 
     deallocate(y_ptr) 

     ! Case 3 
     allocate(y, source=x%fun_copy_alloc()) 
     print *, y%data 
     deallocate(y) 

    end program my_prog 
Các vấn đề liên quan