Jod*_*cus 3 oop polymorphism constructor fortran
我想创建一个多态对象数组,其中的构造函数根据其动态类型采用不同的虚拟参数。在阅读了有关用户定义和结构构造函数的内容后,我发现无法将这些概念应用于动态分配的对象。拥有 C++ 背景,我习惯了在动态或在堆栈上分配对象时可以使用同一个构造函数“成员函数”的概念,但如何在分配的对象上显式调用用户定义的 Fortran 构造函数呢?
相反,我尝试摆弄通用和类型绑定的初始化函数:
module mod
type :: basis_t
contains
procedure, public :: init_func => init_base
! I want a generic constructor function
generic, public :: init => init_func
end type
type, extends(basis_t) :: extended_t
contains
! cannot work, init_extended has a different signature from init_base
procedure, public :: init => init_extended
end type
type wrapper_t
type(basis_t), pointer :: obj
end type
contains
subroutine init_base(this)
class(base_t), intent(inout) :: this
end subroutine
subroutine init_extended(this, param)
class(extended_t), intent(inout) :: this
integer :: param
end subroutine
end module
program
use mod
implicit none
type(wrapper_t) :: arr(2)
allocate(basis_t::arr(1)%obj)
allocate(extended_t::arr(2)%obj)
call arr(1)%obj%init ! calls init_basis
call arr(2)%obj%init(4) ! calls init_extended
end program
Run Code Online (Sandbox Code Playgroud)
但我不相信我走在正确的轨道上,就像在 C++ 中我宁愿这样做
basis_t* arr[2];
arr[0] = new basis_t;
arr[1] = new extended_t{ 4 };
Run Code Online (Sandbox Code Playgroud)
重要的区别是 C++ 中的构造函数不是类型绑定/虚拟的,就像我的 Fortran 方法一样。我能做些什么?
Fortran 中构造函数的作用可以通过以下方式提供:
该语言提供了结构构造函数。
一个函数,其结果是正在构造的对象的类型。该语言允许泛型函数与派生类型具有相同的名称,并进一步允许对此类函数的引用来重载对该类型的结构构造函数的引用。
定义适当类型的intent(out)参数的子例程。
您使用什么在一定程度上取决于环境和个人喜好。语言提供的结构体构造函数在某些情况下可以用在常量表达式中,但只允许组件的简单值定义(不允许执行代码);函数引用形式允许您作为对象构造的一部分执行任意代码,不能在常量表达式中使用,不能轻易指示构造失败,并且如果构造的对象很大,则可能会很昂贵(取决于 Fortran 处理器实现细节);子例程形式需要单独的调用语句(构造函数不能是较大表达式的一部分)并且无法利用通用名称/结构重载语言功能。
这三种方法都不涉及类型绑定过程。在某些情况下,类型绑定过程可能适合对象定义(例如,类型绑定过程旨在从文件中读取对象值 - 扩展层次结构中的所有类型都需要有关要传递到的文件的相同信息)它们),但它对于构造没有一般意义,在构造中您定义对象的类型以及定义其值。
Fortran 中的指针主要用于引用语义(因为它们是引用)。如果您想要值语义,您通常不想使用它们 - 使用可分配项。
TYPE :: ta
INTEGER :: a
END TYPE ta
TYPE, EXTENDS(ta) :: tb
REAL :: b
END TYPE :: tb
INTERFACE tb
PROCEDURE :: tb_construct
END INTERFACE tb
TYPE, EXTENDS(ta) :: tc
END TYPE tc
TYPE :: ta_item
CLASS(ta), ALLOCATABLE :: item
END TYPE ta_item
!...
FUNCTION tb_construct(arg)
INTEGER, INTENT(IN) :: arg
TYPE(tb) :: tb_construct
tb_construct%a = arg + 1
tb_construct%b = arg / 2.0
END FUNCTION tb_construct
SUBROUTINE ConstructTC(obj, arg, stat)
CLASS(ta), INTENT(OUT), ALLOCATABLE :: obj
INTEGER, INTENT(IN) :: arg
INTEGER, INTENT(OUT) :: stat
TYPE(tc), ALLOCATABLE :: tmp
IF (arg < 0) THEN
! Construction failed.
stat = 1
RETURN
END IF
tmp%a = arg + 4
CALL MOVE_ALLOC(tmp, obj)
stat = 0 ! Construction succeeded.
END SUBROUTINE ConstructTC
!...
TYPE(ta_item) :: the_items(3)
INTEGER :: stat
! Structure constructor
the_items(1)%item = ta(1)
! Overloaded function.
the_items(2)%item = tb(2)
! Subroutine.
CALL ConstructTC(the_items(3)%item, 3, stat)
IF (stat /= 0) ERROR STOP 'It failed.'
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
437 次 |
| 最近记录: |