我正在尝试使用指针在对象之间创建链接。使用 Fortran,下面是代码片段:
module base_pars_module
type,abstract,public :: base_pars
end type
end module
module test_parameters_module
use base_pars_module
type, extends(base_pars) :: test_pars
contains
procedure :: whoami
end type
contains
function whoami(this) result(iostat)
class( test_pars) :: this
write(*,*) 'i am a derived type child of base_pars'
end type
end module
module base_mask_module
use base_pars module
type, abstract , public :: base_mask
class(base_pars),pointer :: parameters
end type
end module
module test_mask_module
use base_mask_module
implicit none
type, extends(base_mask) :: test_mask
end type
end module
program driver
type(test_pars) , target :: par_Test
type(test_mask) :: mask_test
iostat= par_test%whoami()
mask_test%parameters=>par_test
iostat=mask_test%parameters%whoami()
end program
base_mask_module
处的 parameters
是一个 base_pars
类的指针。我想使用此指针来引用 par_test
对象,该对象是扩展 base_pars
类型的 test_pars
类型。所以指针和目标具有相同的类。但是当我编译它时,它给出了一个错误:
driver.f90:17.37:
iostat=mask_test%parameters%whoami()
1
Error: 'whoami' at (1) is not a member of the 'base_pars' structure
这是一个错误还是我做错了什么?
最佳答案
当您具有这样的多态性时,需要考虑对象的两件事:其动态类型和其声明类型。 test_mask
(base_mask
) 的 parameters
组件声明为
class(base_pars),pointer :: parameters
因此,此类组件已声明类型 base_pars
。
来指针赋值
mask_test%parameters=>par_test
mask_test%parameters
的动态类型与 par_test
相同:test_pars
。不过,它是声明类型 base_pars
的,当我们关心它的组件和绑定(bind)时,声明类型很重要。 base_pars
确实没有 whoami
。
那么,您需要声明类型为 par_test
的东西。无需更改派生类型的定义,您可以使用select type
构造来完成此操作。
select type (pars => mask_test%parameters)
class is (par_test)
iostat=pars%whoami() ! pars of declared type par_test associated with mask_test%parameters
end select
也就是说,使用这种方法事情很快就会变得非常乏味。始终使用选择类型
,区分众多扩展类型,将是一个相当大的束缚。另一种方法是确保声明的类型 base_pars
具有绑定(bind) whoami
。我们没有像上面那样改变主程序,而是改变模块base_pars_module
:
module base_par_modules
implicit none ! Encourage good practice
type,abstract,public :: base_pars
contains
procedure(whoami_if), deferred :: whoami
end type
interface
integer function whoami_if(this)
import base_pars ! Recall we're in a different scope from the module
class(base_pars) this
end function
end interface
end module
因此,我们在 base_pars
中有一个延迟绑定(bind),稍后会被扩展类型 test_pars
中的绑定(bind)覆盖。主程序中的mask_test%parameters%whoami()
是有效的,调用的函数是动态类型的parameters
提供的函数。
这里的两种方法都解决了参数的声明类型的绑定(bind)问题
。哪种最适合您的实际问题取决于您的整体设计。
如果您知道您的类型层次结构都与基本类型有足够的共同点(也就是说,所有类型都将提供 whoami
绑定(bind)),那么采用第二种方法是有意义的。当您遇到奇怪的特殊情况时,请使用第一种方法,我建议这种情况应该很少见。
关于class - Fortran 指针多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31220961/