指针中的 Fortran 多态性 [英] Fortran polymorphism in pointers
问题描述
我正在尝试使用指针在对象之间创建链接.使用 Fortran,这里是代码段:
I am trying to use pointers to create links between objects. Using Fortran and here is the code piece:
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
类型.所以指针和目标具有相同的类.但是当我编译它时,它给出了一个错误:
parameters
at base_mask_module
is a pointer with base_pars
class. I would like to use this pointer to refer par_test
object which is test_pars
type that extends base_pars
type. So the pointer and the target has the same class. But when I compile this it gives an error:
driver.f90:17.37:
iostat=mask_test%parameters%whoami()
1
Error: 'whoami' at (1) is not a member of the 'base_pars' structure
这是一个错误还是我做错了什么?
Is it a bug or am i doing something wrong?
推荐答案
当你有这样的多态时,关于一个对象需要考虑两件事:它的动态类型和它的声明 类型.test_mask
(base_mask
)的parameters
组件声明为
When you have polymorphism like this there are two things to consider about an object: its dynamic type and its declared type. The parameters
component of test_mask
(base_mask
) is declared as
class(base_pars),pointer :: parameters
因此,此类组件已声明类型 base_pars
.
Such a component therefore has declared type base_pars
.
来个指针赋值
mask_test%parameters=>par_test
mask_test%parameters
具有与 par_test
相同的动态类型:test_pars
.不过,它是声明类型base_pars
,当我们关心它的组件和绑定时,声明类型很重要.base_pars
确实没有 whoami
.
mask_test%parameters
has dynamic type the same as par_test
: test_pars
. It's of declared type base_pars
, though, and it's the declared type that is important when we care about its components and bindings. base_pars
indeed has no whoami
.
那么,您需要声明类型为 par_test
的东西.在不更改派生类型的定义的情况下,您可以使用 select type
构造来完成此操作.
You need, then, something which has declared type par_test
. Without changing the definitions of the derived types you can do this with the select type
construct.
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
也就是说,使用这种方法很快就会变得非常乏味.总是使用select type
,区分众多的扩展类型,会很麻烦.另一种方法是确保声明的类型base_pars
具有绑定whoami
.我们没有像上面那样更改主程序,而是更改模块 base_pars_module
:
That said, things get pretty tedious quite quickly with this approach. Always using select type
, distinguishing between numerous extending types, will be quite a bind. An alternative would be to ensure that the declared type base_pars
has a binding whoami
. Instead of changing the main program as above, we alter the module 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
中有一个延迟绑定,后来被扩展类型 test_pars
中的绑定覆盖.主程序中的mask_test%parameters%whoami()
是有效的,调用的函数是parameters
的动态类型提供的.
So, we've a deferred binding in base_pars
that is later over-ridden by a binding in the extending type test_pars
. mask_test%parameters%whoami()
in the main program is then a valid and the function called is that offered by the dynamic type of parameters
.
这里的两种方法都解决了参数
声明类型的绑定问题.哪种最适合您的实际问题取决于您的整体设计.
Both approaches here address the problem with the binding of the declared type of parameters
. Which best suits your real-world problem depends on your overall design.
如果您知道您的类型层次结构都与基本类型有足够的共同点(即,所有类型都将提供 whoami
绑定),那么采用第二种方法是有意义的.当您遇到奇怪的特殊情况时,请使用第一种方法,我建议这种情况很少见.
If you know that your hierarchy of types will all have enough in common with the base type (that is, all will offer a whoami
binding) then it makes sense to go for this second approach. Use the first approach rather when you have odd special cases, which I'd suggest should be rare.
这篇关于指针中的 Fortran 多态性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!