如何解决通用接口和运算符重载 - 如何将通用接口块中的过程设置为模块中的私有?
我的 IDE 是:Code::Blocks 20.03 (MinGW 9.2.0)
这是我的代码:
module mod_kompleks
use,intrinsic :: iso_c_binding,only : rp => c_double
implicit none
type,public :: kom_bro
real(rp),private :: rea
real(rp),private :: img
contains
procedure,pass(kdt),private :: kom_bro_ini
procedure,public :: uzm_rea => uzm_pod_rea
procedure,public :: uzm_img => uzm_pod_img
procedure,private :: kom_bro_sab
generic,public :: operator(+) => kom_bro_sab
end type kom_bro
interface kom_bro
module procedure kom_bro_kon
end interface kom_bro
private :: kom_bro_kon
contains
function kom_bro_kon( bro_rea,bro_img ) result( bro )
real(rp),intent(in) :: bro_rea
real(rp),intent(in) :: bro_img
type(kom_bro) :: bro
call bro%kom_bro_ini(bro_rea,bro_img)
end function kom_bro_kon
subroutine kom_bro_ini(kdt,dio_rea,dio_img)
class(kom_bro),intent(out) :: kdt
real(rp),intent(in) :: dio_rea
real(rp),intent(in) :: dio_img
kdt%rea = dio_rea
kdt%img = dio_img
end subroutine kom_bro_ini
function uzm_pod_rea( kdt ) result( rez )
class(kom_bro),intent(in) :: kdt
real(rp) :: rez
rez = kdt%rea
end function uzm_pod_rea
function uzm_pod_img( kdt ) result( rez )
class(kom_bro),intent(in) :: kdt
real(rp) :: rez
rez = kdt%img
end function uzm_pod_img
function kom_bro_sab( kdt,bro ) result( rez )
class(kom_bro),intent(in) :: kdt
class(kom_bro),intent(in) :: bro
type(kom_bro) :: rez
rez%rea = kdt%rea + bro%rea
rez%img = kdt%img + bro%img
end function kom_bro_sab
end module mod_kompleks
program kompleksni_broj
use,non_intrinsic :: mod_kompleks
implicit none
type(kom_bro) :: broj_01,broj_02,broj_03
broj_01 = kom_bro(1.1_rp,2.2_rp)
print '(1x,f4.2,1x,"j",1xf4.2)',broj_01%uzm_rea(),broj_01%uzm_img()
broj_02 = kom_bro(3.3_rp,4.4_rp)
print '(1x,broj_02%uzm_rea(),broj_02%uzm_img()
broj_03 = broj_01 + broj_02
print '(1x,broj_03%uzm_rea(),broj_03%uzm_img()
end program kompleksni_broj
我的目的是禁止访问 kom_bro_sab
模块外的 mod_kompleks
过程。如果我想在主程序中用实部和虚部的值构造一个复数,在输入单词 kom 后,我有机会选择过程 kon_bro
,这当然是我想要的,但旁边该函数为我提供了选择过程 kom_bro_sab
的机会。如何防止这种情况(我只希望过程 kom_bro_sab
和运算符 +
可见)?
我将添加我得到的屏幕截图,即使类型绑定过程是私有的:
解决方法
简而言之
kom_bro_sab
函数具有(默认)访问属性 public
,这就是您可以在主程序中访问 kom_bro_sab
的原因。
说明
函数 kom_bro_sab
与任何其他函数一样被导出,因为它的访问属性是 public
。
这是因为默认情况下,访问属性为 public
,此处未更改。
不要被 procedure,pass(kdt),private :: kom_bro_sab
行混淆。
这里定义了一个类型绑定过程kom_bro_sab
,它具有访问属性private
。
因此,您只能从其他类型绑定过程调用此属性。
您应该区分类型绑定过程和函数本身。
解决方案
有两种处理方式。
- 将默认访问属性更改为
private
并仅显式定义public
实体。这也使得在快速查看模块以查看实际导出的实体时更容易。
module mod_kompleks
use,intrinsic :: iso_c_binding,only : rp => c_double
implicit none
private
public kom_bro
type kom_bro
...
end module
- 您可以通过显式定义
public
和private
属性来保持您正在执行的操作。然后你只需要添加一行(参见包含ADDED
的行)。
module mod_kompleks
use,only : rp => c_double
implicit none
type,public :: kom_bro
...
end interface kom_bro
private kom_bro_kon
private kom_bro_sab ! <- ADDED
...
end module
我缩短了您的代码并希望它仍然可以理解。
,为了让重载的 operator(+)
工作
broj_03 = broj_01 + broj_02
我们需要考虑三个不同的方面:
- 模块过程
kom_bro_sab
- 绑定名称为
kom_bro_sab
的特定类型绑定过程 - 通用类型绑定接口
operator(+)
每一个都有自己的可访问性,并且是一个独特的东西。
看看我们的声明。在
broj_03 = broj_01 + broj_02
我们可以看到,当我们考虑泛型 operator(+)
时,我们有左侧 class(kom_bro)
和右侧 class(kom_bro)
:我们匹配特定类型绑定过程kom_bro_sab
。我们可以在模块之外进行这个评估,因为这个通用接口是public。此解决方案不需要公开特定的类型绑定过程。
假设绑定名称是可访问的,前面的语句可以写成对特定类型绑定过程的引用,如下所示
broj_03 = broj_01%kom_bro_sab(broj_02)
最后,假设模块过程是可访问的,看起来像
broj_03 = kom_bro_sab(broj_01,broj_02)
我们可以独立控制对这些东西的访问。
在问题的代码中,您有特定的绑定 kom_bro_sab
私有,但模块过程 kom_bro_sab
是公共的,因为模块的默认可访问性是公共的。
jack's answer 展示了如何将默认可访问性设为私有,或将默认可访问性设为公开但将模块过程设为私有。您已经指定了对特定和通用绑定的所需访问权限。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。