通用接口和运算符重载 - 如何将通用接口块中的过程设置为在模块中私有?
Generic interfaces and operator overloading - how to set procedure from generic interface block to be private in module?
我的 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, pass(kdt), public :: uzm_rea => uzm_pod_rea
procedure, pass(kdt), public :: uzm_img => uzm_pod_img
procedure, pass(kdt), 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,f4.2,1x,"j",1xf4.2)', broj_02%uzm_rea(), broj_02%uzm_img()
broj_03 = broj_01 + broj_02
print '(1x,f4.2,1x,"j",1xf4.2)', broj_03%uzm_rea(), broj_03%uzm_img()
end program kompleksni_broj
我的目的是禁止在 mod_kompleks
模块外访问 kom_bro_sab
过程。如果我想在主程序中用实部和虚部的值构造一个复数,在输入 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
搞糊涂了。
这里定义了一个 type-bound 过程 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, intrinsic :: iso_c_binding, 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。此解析不需要特定类型绑定过程 public.
假设绑定名称是可访问的,前面的语句可以写成对特定类型绑定过程的引用,如下所示
broj_03 = broj_01%kom_bro_sab(broj_02)
最后,假设模块过程是可访问的,看起来像
broj_03 = kom_bro_sab(broj_01, broj_02)
我们可以独立控制对这些东西的访问。
在问题的代码中,您有特定的绑定 kom_bro_sab
private,但是模块过程 kom_bro_sab
是 public 因为模块的默认可访问性是 public.
展示了如何将默认可访问性设置为私有,或者具有默认可访问性 public 但将模块过程设置为私有。您已经指定了对特定绑定和通用绑定的访问权限。
我的 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, pass(kdt), public :: uzm_rea => uzm_pod_rea
procedure, pass(kdt), public :: uzm_img => uzm_pod_img
procedure, pass(kdt), 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,f4.2,1x,"j",1xf4.2)', broj_02%uzm_rea(), broj_02%uzm_img()
broj_03 = broj_01 + broj_02
print '(1x,f4.2,1x,"j",1xf4.2)', broj_03%uzm_rea(), broj_03%uzm_img()
end program kompleksni_broj
我的目的是禁止在 mod_kompleks
模块外访问 kom_bro_sab
过程。如果我想在主程序中用实部和虚部的值构造一个复数,在输入 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
搞糊涂了。
这里定义了一个 type-bound 过程 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, intrinsic :: iso_c_binding, 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。此解析不需要特定类型绑定过程 public.
假设绑定名称是可访问的,前面的语句可以写成对特定类型绑定过程的引用,如下所示
broj_03 = broj_01%kom_bro_sab(broj_02)
最后,假设模块过程是可访问的,看起来像
broj_03 = kom_bro_sab(broj_01, broj_02)
我们可以独立控制对这些东西的访问。
在问题的代码中,您有特定的绑定 kom_bro_sab
private,但是模块过程 kom_bro_sab
是 public 因为模块的默认可访问性是 public.