For*_*Cpp 14 polymorphism inheritance fortran overriding
我试图理解Fortran 2003标准(或更高版本)中面向对象的概念.我对C++有一些了解,所以我认为这两种语言之间有一些共同点,可以帮助我更好地理解它们.
在C++中,多态性是通过类派生和成员函数覆盖来完成的.一个定义了一个"抽象"基类,几乎所有的虚函数都被定义了.不同的派生类包含它们的实际实现.所以其他函数只需要基于"抽象"类进行编程.然后它们适用于所有派生类.
我认为在Fortran中,OOP以类似的方式完成,但存在一些差异.在我看来,需要定义一个带有一些虚函数的基类型,就像C++一样.其他函数/子例程应遵循基类型中的成员函数定义.这是解决所有扩展类型的函数/子例程重用的方法.
我对如何编写这个想法没有更好的想法.这是我的第一次尝试:
type Basis
integer :: NBasis
contains
private
procedure :: DoNothing
generic, public :: Constructor => DoNothing
generic, public :: AllocateBasis => DoNothing
endtype Basis
type, extends(Basis) :: GridBasis
private
integer :: NGrid
contains
private
procedure :: ConstructorGrid1
procedure :: ConstructorGrid2
generic, public :: Constructor => ConstructorGrid1, ConstructorGrid2, ConstructorGrid3
procedure :: AllocateGridReal
procedure :: AllocateGridCplx
generic, public :: AllocateBasis => AllocateGridReal, AllocateGridCplx
endtype GridBasis
Run Code Online (Sandbox Code Playgroud)
首先,我如何在类型Basis中定义"AllocateBasis",使其像"虚函数"一样工作,所有扩展类型必须定义自己的"AllocateBasis"版本?
其次,如何在GridBasis类型中定义"AllocateBasis"?这里的定义包含它的真实实现.
第三,如何在GridBasis类型中使"AllocateBasis"成为重载函数?即存在真实版本和复杂版本,并且它们都被命名为"AllocateBasis",具有实际或复杂的输入可分配数组.
第四,NOPASS与PASS.据我所知,如果设置了PASS,那么就会有一个指向该对象的显式指针.但是当NOPASS设定时,就没有这样的东西了.那么PASS是简化澄清的吗?
Bál*_*adi 17
首先是您的问题的一些评论/答案:
您可以声明一个类型绑定过程deferred
.然后,您必须在没有特定实现的情况下定义其签名(接口).deferred
必须声明包含该过程的类型abstract
.这些类型无法实例化.所有扩展类型必须为给定的过程提供实现,除非它们本身abstract
.
为了deferred
在扩展类型中提供过程的实现,您只需在扩展类型中声明过程并为其提供实现.
您无法将给定类型的公共过程转换为generic
扩展类型.但是,您可以generic
在基类型中定义已扩展并在其派生类型中扩展它.
该pass
属性默认设置,因此该过程的第一个参数将是类型实例.但是,您可以指定它以使其更明确.另外,您可以在表单中使用它PASS(ARGNAME)
来指定哪个argument(ARGNAME
)应该是实例.这个论点不一定是程序中的第一个.
下面是一个包含自我的示例,其中应包含您要求的所有功能:
module basis_module
implicit none
type, abstract :: Basis
integer :: NBasis
contains
procedure(allocBasisR1Interface), deferred :: allocateBasisR1
generic :: allocateBasis => allocateBasisR1
end type Basis
interface
! Interface for real basis allocation
subroutine allocBasisR1Interface(self, array)
import
class(Basis), intent(inout) :: self
real, intent(in) :: array(:)
end subroutine allocBasisR1Interface
end interface
end module basis_module
module extension_module
use basis_module
implicit none
type, extends(Basis) :: GridBasis
contains
! Extending the mapping allocateBasis => allocateBasisR1 of
! the parent type.
generic :: allocateBasis => allocateBasisC1
procedure :: allocateBasisC1
! Implementation for the deferred procedure in Basis
procedure :: allocateBasisR1
end type GridBasis
contains
subroutine allocateBasisR1(self, array)
class(GridBasis), intent(inout) :: self
real, intent(in) :: array(:)
self%NBasis = size(array)
print *, "GridBasis:allocateBasisR1"
end subroutine allocateBasisR1
subroutine allocateBasisC1(self, array)
class(GridBasis), intent(inout) :: self
complex, intent(in) :: array(:)
self%NBasis = size(array)
print *, "GridBasis:allocateBasisC1"
end subroutine allocateBasisC1
end module extension_module
program test
use extension_module
implicit none
type(GridBasis) :: mybasis
real :: myRealArray(10)
complex :: myComplexArray(5)
call mybasis%allocateBasis(myRealArray)
call mybasis%allocateBasis(myComplexArray)
end program test
Run Code Online (Sandbox Code Playgroud)