Inheritance 理解Fortran扩展了类型和覆盖
我试图理解Fortran 2003标准(或更高版本)中的面向对象概念。我在C++中有一些知识,所以我认为这两种语言之间有一些共同的想法,这可以帮助我更好地理解它们。p> 在C++中,多态性是通过类派生和成员函数重写来完成的。其中一个定义了一个“抽象”基类,其中定义了几乎所有的虚函数。不同的派生类包含它们的实际实现。所以其他函数只需要基于“抽象”类进行编程。然后,它们适用于所有派生类 我认为在Fortran中,OOP是以类似的方式完成的,但有一些不同之处。在我看来,需要定义一个具有C++的一些虚拟函数的基类型。其他函数/子例程应遵循基类型中的成员函数定义。这是解决所有扩展类型的函数/子例程重用问题的方法 我没有更好的办法来规划这个想法。这是我的第一次尝试:Inheritance 理解Fortran扩展了类型和覆盖,inheritance,polymorphism,fortran,overriding,Inheritance,Polymorphism,Fortran,Overriding,我试图理解Fortran 2003标准(或更高版本)中的面向对象概念。我在C++中有一些知识,所以我认为这两种语言之间有一些共同的想法,这可以帮助我更好地理解它们。p> 在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
- 首先,我如何在类型基础中定义“AllocateBasis”,使其像“虚拟函数”一样工作,并且所有扩展类型都必须定义自己版本的“AllocateBasis”
- 第二,如何在GridBasis类型中定义“AllocateBasis”?这里的定义包含了它的实际实现
- 第三,如何使GridBasis类型中的“AllocateBasis”成为重载函数?i、 e.有实版本和复版本,它们都被命名为“AllocateBasis”,具有实或复输入可分配数组
- 第四,不传球对传球。据我所知,如果设置了PASS,则有一个指向该对象的显式指针。但是,当没有通行证时,就没有这样的事情。那么,通行证是为了澄清而简化的吗
- 您可以将类型绑定过程声明为“延迟”。然后您必须只定义它的签名(接口),而不需要特定的实现。必须声明包含
过程的类型延迟
。此类类型无法实例化。所有扩展类型都必须为给定过程提供实现,除非它们本身是摘要
抽象的
- 为了在扩展类型中为延迟的过程提供实现,只需在扩展类型中声明该过程并为其提供实现
- 不能将给定类型的公共过程转换为扩展类型中的
泛型
。但是,您可以在基类型中定义一个
泛型
,并在其派生类型中对其进行扩展
- 默认情况下设置
属性,因此过程的第一个参数将是类型实例。但是,您可以指定它以使其更明确。此外,您可以在pass
的形式中使用它来指定哪个参数(PASS(ARGNAME)
)应该是实例。此参数不必是过程中的第一个参数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
我的目标是分离解算器例程和基本类型。你是对的。我会立即在我的帖子中添加一个例子。谢谢你的回答:)你现在有了一个合理的一般答案,很容易适应你的具体情况。你的编辑澄清了你知道你不需要在任何地方都做基本的事情(但在这里很有用)!谢谢让我消化一会儿。好奇的是:你在不同的模块中分离基类型和扩展类型,或者仅仅是你的编程风格,这是我的编程风格,每种类型都使用不同的模块进行类型绑定。@Bálint Aradi,我知道这是一个过时的线程,但这段代码是否运行过?它在IVF 2012下生成了一个与符号“\u allocBasisR1Interface”相关的LNK2019错误,我缺乏必要的知识来修复它。@IronX是的。我刚刚试过gfortran 8.2。