通用接口和运算符重载 - 如何将通用接口块中的过程设置为模块中的私有?

如何解决通用接口和运算符重载 - 如何将通用接口块中的过程设置为模块中的私有?

我的 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

解决方法

简而言之

kom_bro_sab 函数具有(默认)访问属性 public,这就是您可以在主程序中访问 kom_bro_sab 的原因。

说明

函数 kom_bro_sab 与任何其他函数一样被导出,因为它的访问属性是 public。 这是因为默认情况下,访问属性为 public,此处未更改。

不要被 procedure,pass(kdt),private :: kom_bro_sab 行混淆。 这里定义了一个类型绑定过程kom_bro_sab,它具有访问属性private。 因此,您只能从其他类型绑定过程调用此属性。 您应该区分类型绑定过程和函数本身。

解决方案

有两种处理方式。

  1. 将默认访问属性更改为 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
  1. 您可以通过显式定义 publicprivate 属性来保持您正在执行的操作。然后你只需要添加一行(参见包含 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 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-