Исследователь
Профиль
Группа: Участник Клуба
Сообщений: 1693
Регистрация: 3.4.2005
Где: Санкт-Петербург, Россия
Репутация: 1 Всего: 41
|
Ау Я, например, фортранист. На Винграде есть всё. У интерфейсов есть много назначений. Внутри себя они так или иначе содержат заголовки процедур. Делается это для разных целей. 1. Перегрузка процедур.Можо под одним именем (родовым) определить несколько процедур. Более того, объединяемые процедуры могут содержать разное число параметров. Под одним именем могут быть перегружены одновременно и подпрограммы, и функции, с разным числом параметров. Пример 1.1Код | program Interfaces
implicit none
! Объединяем под одним родовым именем функции и подпрограмму. interface Maximum ! Заголовки процедур с их специфическими именами.
function IntegerMax( int1, int2 ) integer IntegerMax, int1, int2 end
function RealMax( real1, real2 ) real RealMax, real1, real2 end
subroutine CharacterMax( char1, char2, char3 ) character(*) char1, char2, char3 end end interface Maximum
integer :: i1 = 3, i2 = 4 real :: r1 = 4, r2 = 5 character(*), parameter :: char1 = "Welcome" character(*), parameter :: char2 = "Vingrad," character(*), parameter :: char3 = "Lera!"
! Используя родовое имя, вызываем каждый раз свою процедуру. print *, Maximum( i1, i2 ), Maximum( r1, r2 ) call Maximum( char1, char2, char3 )
read *
end program Interfaces
! Используемые процедуры определены вне программы. function IntegerMax( int1, int2 ) integer IntegerMax, int1, int2
IntegerMax = Max( int1, int2 ) end function IntegerMax
function RealMax( real1, real2 ) real RealMax, real1, real2
RealMax = Max( real1, real2 ) end function RealMax
subroutine CharacterMax( char1, char2, char3 ) character(*) char1, char2, char3
print *, Max( Len(char1), Len(char2) ) end subroutine CharacterMax
|
Результат выполненияТак в отдельном месте, непонятно где (в том же файле) определять процедуры считается плохим тоном. Можно включить процедуры в саму программу, тогда процедуры станут модульными, а родовой интерфейс будет задаваться более компактно. Пример 1.2Код | program Interfaces
implicit none
! Объединяем под одним родовым именем функции и подпрограмму. interface Maximum ! Заголовки процедур с их специфическими именами. Указаны только имена ! процедур, т.к. они определены в этом же модуле (а данном случае -- в ! программе). module procedure IntegerMax, RealMax, CharacterMax end interface Maximum
integer :: i1 = 3, i2 = 4 real :: r1 = 4, r2 = 5 character(*), parameter :: char1 = "Welcome" character(*), parameter :: char2 = "Vingrad," character(*), parameter :: char3 = "Lera!"
! Используя родовое имя, вызываем каждый раз свою процедуру. print *, Maximum( i1, i2 ), Maximum( r1, r2 ) call Maximum( char1, char2, char3 )
read *
! Используемые процедуры определены внутри программы. contains function IntegerMax( int1, int2 ) integer IntegerMax, int1, int2
IntegerMax = Max( int1, int2 ) end function IntegerMax
function RealMax( real1, real2 ) real RealMax, real1, real2
RealMax = Max( real1, real2 ) end function RealMax
subroutine CharacterMax( char1, char2, char3 ) character(*) char1, char2, char3
print *, Max( Len(char1), Len(char2) ) end subroutine CharacterMax end program Interfaces
|
Процедуры вместе с интерфейсом можно определить внутри модуля, тем самым облегчив текст программы. Пример 1.3Код | program Interfaces
use Procedures implicit none integer :: i1 = 3, i2 = 4 real :: r1 = 4, r2 = 5 character(*), parameter :: char1 = "Welcome" character(*), parameter :: char2 = "Vingrad," character(*), parameter :: char3 = "Lera!"
! Используя родовое имя, вызываем каждый раз свою процедуру,. print *, Maximum( i1, i2 ), Maximum( r1, r2 ) call Maximum( char1, char2, char3 )
read * end program Interfaces
|
Код | module Procedures
implicit none
! Объединяем под одним родовым именем функции и подпрограмму. interface Maximum ! Заголовки процедур с их специфическими именами. Указаны только имена ! процедур, т.к. они определены в этом же модуле (а данном случае -- в ! модуле). module procedure IntegerMax, RealMax, CharacterMax end interface Maximum
! Используемые процедуры определены внутри модуля. contains function IntegerMax( int1, int2 ) integer IntegerMax, int1, int2
IntegerMax = Max( int1, int2 ) end function IntegerMax
function RealMax( real1, real2 ) real RealMax, real1, real2
RealMax = Max( real1, real2 ) end function RealMax
subroutine CharacterMax( char1, char2, char3 ) character(*) char1, char2, char3
print *, Max( Len(char1), Len(char2) ) end subroutine CharacterMax end module Procedures
|
Более того, саму перегрузку можно делать в программе. В модуле процедуры будут только описаны, но не объединены под одним именем. Пример 1.4Код | program Interfaces
use Procedures implicit none ! Объединяем под одним родовым именем функции и подпрограмму. interface Maximum ! Заголовки процедур с их специфическими именами. Указаны только имена ! процедур, т.к. они определены в этом же модуле (а данном случае -- в ! модуле). module procedure IntegerMax, RealMax, CharacterMax end interface Maximum integer :: i1 = 3, i2 = 4 real :: r1 = 4, r2 = 5 character(*), parameter :: char1 = "Welcome" character(*), parameter :: char2 = "Vingrad," character(*), parameter :: char3 = "Lera!"
! Используя родовое имя, вызываем каждый раз свою процедуру,. print *, Maximum( i1, i2 ), Maximum( r1, r2 ) call Maximum( char1, char2, char3 )
read * end program Interfaces
|
Код | module Procedures
implicit none
! Используемые процедуры определены внутри модуля. contains function IntegerMax( int1, int2 ) integer IntegerMax, int1, int2
IntegerMax = Max( int1, int2 ) end function IntegerMax
function RealMax( real1, real2 ) real RealMax, real1, real2
RealMax = Max( real1, real2 ) end function RealMax
subroutine CharacterMax( char1, char2, char3 ) character(*) char1, char2, char3
print *, Max( Len(char1), Len(char2) ) end subroutine CharacterMax end module Procedures
|
2. Перегрузка присваивания и операцийИнтерфейс может объединять под собой процедуры, которые будут вызываться при использованиии соответствующих операций. В этом случае он имеет следующий вид. Код | interface operator(op)
|
op -- существующий или придуманный оператор. Последнее поддерживают немногие языки. Процедуры, которые задают операции должны обязательно быть функциями, которые содержат один параметр в случае определения унарной операции и два параметра в случае определения бинарной рперации. Оба параметра должны иметь вид связи in: intent(in). Процедуры могут быть модульными и нет. Весь предыдущий раздел по виду подробности описания распространяется и на этот случай. При перегрузке присваивания интерфейс имеет вид: Код | interface assignment(=)
|
Процедуры внутри такого интерфейса должны быть обязательно подпрограммами с двумя аргументами. Первый из них -- тот, к которому присваиваем значение, должен имееть вид связи out или inout. Второй аргумент -- тот, значение которого присваиваем другому, должен иметь вид связи in. Пример 2.1Код | program Interfaces
use PointType implicit none type(Point) point1, point2 ! Используем операцию присваивания точке комплексного числа. point1 = (3.7, 8.2) point2 = (6.3, 1.8) ! Используем операцию сложения. point1 = point1 + point2 print *, point1
read * end program Interfaces
|
Код | module PointType implicit none type Point real x real y end type Point ! Задаем операцию присваивания точке комплексного числа. interface assignment(=) module procedure AssignIntegerToPoint end interface assignment(=) ! Задаем операцию сложения точек. interface operator(+) module procedure SumPoints end interface operator(+) contains
subroutine AssignIntegerToPoint( dot, compl ) type(Point), intent(inout) :: dot complex, intent(in) :: compl ! Используем конструктор. dot = Point( Real(compl), Imag(compl) ) ! Это равносильно: !dot%x = Real(compl) !dot%y = Imag(compl) end subroutine AssignIntegerToPoint function SumPoints( point1, point2 ) type(Point) SumPoints type(Point), intent(in) :: point1, point2 ! Используем конструктор. SumPoints = Point( point1%x + point2%x, point1%y + point2%y ) ! Это равносильно: !SumPoints%x = point1%x + point2%x !SumPoints%y = point1%y + point2%y end function SumPoints end module PointType
|
Результат выполненияВместо оператора + можно было бы написать .plus.. Тогда код выглядел бы так: Пример 2.2Код | program Interfaces ...
! Используем операцию сложения. point1 = point1 .plus. point2 ... end program Interfaces
|
Код | module PointType ... ! Задаем операцию сложения точек . interface operator(.plus.) module procedure SumPoints end interface operator(.plus.)
... end module PointType
|
Указывать родовое имя, присваивание или перегружаемый оператор в операторе end interface необязательно. 3. Определение внешних процедурТут следует посмотреть на Пример 1.1. Процедуры определены вне какого-то модуля, на который можно было бы ссылаться. Тем не менеее процедуры содержаться в исходных файлах проекта. В данном случае они описаны в том же файле, что и основная программа. Чтобы иметь возможность обращаться к ним, их заголовки и были описаны в интерфейсе. При этом не обязательно давать им родовое имя, оно может отсутсвовать, если нам достаточно будет обращения через их фактические внешние имена. Процедуры после определения в интерфейсном блоке приобретают атрибут external. Имена процедур с атрибутом external могут быть использованы в качестве параметров других процедур. Этот атрибут применяется также для замены встроенной процедуры на пользовательскую. В интерфейсе можно указать директивы компилятора, чтобы, например, обратиться к процедуре, содержащейся в DLL. Если не пользуетесь DLL, то не стоит забивать себе голову. Пример 3.Код | interface function FMin( ax, bx, F, tol ) !DEC$ ATTRIBUTES DLLIMPORT, STDCALL, DECORATE, ALIAS : "_FMin" :: FMin
interface function F( x ) !DEC$ ATTRIBUTES STDCALL :: F
real F real, intent(in) :: x end function F end interface
real FMinS real, intent(in) :: ax, bx, tol end function FMin end interface
|
Это сообщение отредактировал(а) Cr@$h - 25.1.2006, 14:05
|