我正在尝试使用 Fortran 2003 的一些面向对象的功能,但遇到了一些麻烦。首先,我有一个抽象数据类型 sparse_matrix:
type, abstract :: sparse_matrix
(some data)
contains
procedure(matrix_vector_multiply), deferred :: matvec
end type sparse_matrix
abstract interface
subroutine matrix_vector_multiply(A,x,y)
import :: sparse_matrix
class (sparse_matrix), intent(in) :: A
real(kind=8), dimension(:) :: x,y
end subroutine matrix_vector_multiply
end abstract interface
然后我有一个从 sparse_matrix 继承的具体数据类型
type, extends(sparse_matrix) :: csr_sparse_matrix
(some more data)
contains
procedure :: matvec => csr_matvec
end type csr_sparse_matrix
以及matvec的实际实现:
subroutine csr_matvec(A,x,y)
class (csr_sparse_matrix), intent(in) :: A
real(kind=8), dimension(:) :: x,y
(do stuff)
end subroutine csr_matvec
后来,我想在不同的模块中使用 matvec,我不在乎我有哪种动态类型:
subroutine solve(A,x,b,tolerance)
class (sparse_matrix), intent(in) :: A
real(kind=8), dimension(:), intent(in) :: b
real(kind=8), dimension(:), intent(out) :: x
real(kind=8), intent(in) :: tolerance
real(kind=8), dimension( A%nrow ) :: z
call A%matvec(b,z)
(more stuff)
end subroutine solver
我的理解是,无论动态类型 A 是什么,只要子例程matvec
在子数据类型中被覆盖,一切都应该正常工作。
这段代码编译得很好,但是当我运行它时它会出现错误。当我在程序中更改矩阵的声明solve
如下:
class (csr_sparse_matrix), intent(in) :: A
它工作得很好。同样,如果我将 A 保留为 sparse_matrix 但使用
select type(A)
type is (csr_sparse_matrix)
(the same stuff)
end select
然后一切都运行良好。但这首先破坏了覆盖抽象类型过程的整个目的——程序不应该关心我使用的是哪种矩阵,只要它可以执行矩阵向量乘法。
无论如何,我确定这只是我忘记包含的某些属性的问题,但我无法弄清楚它是什么。