2014-09-26 4 views
0

FORTRAN oop 기능으로 프로그래밍 중입니다. 이제 다른 서브 루틴을 인수로 사용하는 서브 루틴이 있습니다. 그러나 나는 서브 루틴이 일반적인 서브 루틴뿐 아니라 무제한 다형성 서브 루틴을 인수로 사용하기를 원한다. 예를 들어 내가 가진 :FORTRAN : 인수 및 다른 문제로 무제한 다형성 서브 루틴 전달

subroutine PassFunc(MyFunc, MyInput) 
     class(*), intent(inout) :: MyInput 
     interface 
      subroutine MyFunc(A, B) 
       class(*), intent(in) :: A 
       class(*), intent(out) :: B 
      endsubroutine MyFunc 
     endinterface 
     class(*), allocatable :: FuncRes 

     select type(MyInput) 
     type is(real(8)) 
      allocate(real(8)::FuncRes) 
      select type(FuncRes) 
      type is(real(8)) 
       call MyFunc(MyInput, FuncRes) 
       MyInput = MyInput + FuncRes**2 
      endselect 
     type is(complex(8)) 
     endselect 
    endsubroutine PassFunc 

    !Input Functions 
    subroutine Func1(A, B) 
     class(*), intent(in) :: A 
     class(*), intent(out) :: B 

     select type(A) 
     type is(real(8)) 
      select type(B) 
      type is(real(8)) 
       B = A + 1 
      endselect 
     type is(complex(8)) 
      select type(B) 
      type is(complex(8)) 
       B = A - 1 
      endselect 
     endselect 
    endsubroutine Func1 

    subroutine Func2(A, B) 
     real(8), intent(in) :: A 
     real(8), intent(out) :: B 

     B = A + 1 
    endsubroutine Func2 

질문 : 난 단지 "PassFunc"로 제한 다형성 서브 루틴을 통과 할 수 있어요

  1. 합니다. 나는 정상적인 함수 (클래스 (*)가없는 함수)를 전달할 수 없다. "PassFunc"가 다른 유형의 함수를 사용하도록 만들 수있는 방법이 있습니까? (예 : Func1은 작동하지만 Func2는 그렇지 않습니다.) 컴파일 할 때 불평하지 않았지만 IVF로 액세스 위반이 있습니다. 작동 가능합니까? 가능한 경우 수정하지 않고 다른 서브 루틴을 사용할 수 있습니다.)

  2. "FuncRes"변수의 유형은 "MyInput"에 따라 다릅니다. 이제 내가 아는 유일한 방법은 중첩 된 선택 유형을 사용하는 것입니다. 그러나 실제로 "FuncRes"와 "MyInput"은 항상 같은 유형이므로 중첩 된 선택 유형을 줄이는 방법이 있습니까? (중간 변수가 많은 경우 재앙이됩니다.)

답변

1

은 예제 코드에는 기능이 없습니다.

다형성 인수있는 절차는 절차가 참조하는 절차에 대한 명시 적 인터페이스를 필요로하거나 절차가 때 대상은 포인터 할당입니다 명시 적 인터페이스가 필요한 프로 시저를 참조하는 포인터도 명시 적 인터페이스가 있어야합니다.이 모든 것은 사실상 이 있어야 함을 의미합니다. 네가 사용하기를 원한다면 명시적인 인터페이스가 필요한 절차를위한 명시 적 인터페이스.

명시 적 인터페이스가 관련된 경우에는 가명 인수와 연관된 프로 시저의 특성이 일치해야합니다. 선언 된 인수 유형은 프로 시저의 특성이므로 인수는 선언 된 유형과 일치해야합니다. 여기서 일치는 "동일 함"을 의미하며, 어떤면에서는 호환이 충분하지 않습니다.

명시 적 인터페이스를 사용할 수 있으면 컴파일러는 인터페이스가 일치하는지 확인할 수 있어야합니다. 그들은 검사 할 필요가 없지만 불일치를 발견하지 못하면 컴파일러 버그로 간주 될 것입니다.

따라서 다형 인자가 관련되어 있으면 다른 유형의 절차를 수행 할 방법이 없습니다.

그러나 일반적으로 PassFunc가 원하는 인터페이스와 일치하는 프로 시저의 래퍼를 작성하지 않으므로 (대신 PassFunc에 전달하므로) Func2를 호출 할 수 있습니다.

두 번째 질문에 대한
SUBROUTINE Func2_wrapper(A,B) 
    CLASS(*), INTENT(IN) :: A 
    CLASS(*), INTENT(OUT) :: B 
    SELECT TYPE (A) 
    TYPE IS (REAL) 
    SELECT TYPE (B) 
    TYPE IS (REAL) 
     CALL Func2(A,B) 
    END SELECT 
    END SELECT 
END SUBROUTINE Func2_wrapper 

, 구현의 선택한 방법으로 중첩을 피할 수있는 일반적인 방법이 없다 - 당신이 FUNC1이 인수에 던져 어떤 유형을 처리하려는 경우 (멀리 더 나쁜 상황이 유형의 조합입니다).

그러나 대체 디자인을 사용하면 단일 단계에서 벗어날 수 있습니다. 그것은 당신이하려고하는 것에 다소 의존합니다 ...더 적절한 접근법은 데이터를 실제로 저장하는 (무제한의 다형 변수를 사용하지 않는) 확장을 사용하여 추상 부모 유형의 지연된 바인딩 인 Func1, Func2 등을 생성 한 다음 이들의 재정의와 같은 연산의 구현을 제공하는 것일 수 있습니다 지연 바인딩. 이것은 이전 질문의 첫 번째 접근법에 더 가깝습니다.

+0

귀하의 설명에 감사드립니다. 이 게시물은 실제로 내 이전 게시물의 확장입니다. 현재 데이터 형식 차이를 숨기기 위해 부모 확장 형식을 사용하는 것이 로컬 변수 문제 때문에 더 좋은 방법입니다. 또한 래퍼가 제공되지 않으면 무제한의 다형성 서브 루틴을 사용할 수 없습니다. 향후 FORTRAN 표준에서 입력 종속 유형에 대한 업데이트가 있기를 바랍니다. – FortCpp