Полный объектно-ориентированный пример с fortran 2003?

Может ли кто-нибудь привести пример того, как это должно быть для простого объектно-ориентированного макета Fortran 2003, эквивалентного этому коду C++:

stefanos-imac:tmp borini$ more Animal.h 
class Animal {
    public:
        Animal(int age);
        ~Animal();
        virtual void speak();
        int getAge();
    private:
        int age;
};

stefanos-imac:tmp borini$ more Animal.cpp 
#include <Animal.h>
#include <iostream>
Animal::Animal(int age) {
    std::cout << "init animal" << age << std::endl;
    this->age = age;
}
Animal::~Animal() {
    std::cout << "dtor animal" << std::endl;
}
void Animal::speak() {
    std::cout << "speak not reimplemented" << std::endl;
}
int Animal::getAge() {
    return this->age;
}
stefanos-imac:tmp borini$ more Cat.h 
#include <Animal.h>
class Cat : public Animal {
    public:
        Cat(int age);
        ~Cat();
        virtual void speak();
};
stefanos-imac:tmp borini$ more Cat.cpp 
#include <Cat.h>
#include <iostream>
Cat::Cat(int age) : Animal(age) {
    std::cout << "init cat" << std::endl;
}
Cat::~Cat() { 
    std::cout << "dtor cat" << std::endl;
}
void Cat::speak() {
    std::cout << "meow" << std::endl;
}
stefanos-imac:tmp borini$ more main.cpp 
#include <iostream>
#include <Cat.h>

int main() {
    Cat c(10);

    std::cout << c.getAge() <<std::endl;
    c.speak();
}

У меня проблемы с моим кодом, см. следующее

stefanos-imac:oop borini$ more Animal.f90 
module AnimalModule
   implicit none
   private
   public :: AnimalType

   type :: AnimalType
      private
      integer :: age
   contains
      procedure :: getAge 
      procedure :: speak
      final :: dtor
   end type

   interface AnimalType
      module procedure ctor
   end interface
contains 
   subroutine ctor(self, age)
      type(AnimalType), intent(inout) :: self
      integer :: age
      print *, "Constructor Animal"
      self%age = age
   end subroutine 
   subroutine dtor(self)
      type(AnimalType), intent(inout) :: self
      print *, "Destroying animal"
   end subroutine 

   function getAge(self)
      class(AnimalType), intent(inout) :: self
      integer :: getAge
      getAge = self%age
   end function
   subroutine speak(self)
      class(AnimalType), intent(in) :: self

      print *, "Animal::speak not overridden"
   end subroutine
end

stefanos-imac:oop borini$ more Cat.f90 
module CatModule
   use AnimalModule
   implicit none
   private

   type, extends(AnimalType) :: CatType
      private
   contains
      procedure :: speak 
      final :: dtor
   end type

   interface CatType
      module procedure ctor
   end interface

contains 
   subroutine ctor(self, age)
      type(CatType), intent(inout) :: self
      integer, intent(in) :: age
      print *, "Constructor Cat"
      self%AnimalType = AnimalType(age)
   end subroutine 
   subroutine dtor(self)
      type(CatType), intent(inout) :: self
      print *, "Destroying Cat"
   end subroutine 
   subroutine speak(self)
      class(CatType), intent(in) :: self

      print *, "Meow"
   end subroutine
end

stefanos-imac:oop borini$ ifort Animal.f90 Cat.f90 
Cat.f90(10): error #8341: Final subroutines are not inherited through type extension and cannot be overridden.   [DTOR]
      final :: dtor
---------------^
Cat.f90(22): error #6292: The parent type of this field is use associated with the PRIVATE fields attribute   [AGE]
      self%AnimalType = AnimalType(age)
-----------------------------------^
compilation aborted for Cat.f90 (code 1)
stefanos-imac:oop borini$ 

В частности, мне непонятно, как инициализировать базовый класс и как определить деструктор для производного класса.

Спасибо


person Stefano Borini    schedule 13.06.2012    source источник


Ответы (1)


   subroutine ctor(self, age)
      type(CatType), intent(inout) :: self
      integer, intent(in) :: age
      print *, "Constructor Cat"
      self%AnimalType = AnimalType(age)
   end subroutine

Это не правильно. CatType не имеет компонента AnimalType. Он расширяет тип AnimalType. ctor — это подпрограмма, и вы используете ее как функцию. Я предлагаю вам определить конструктор (но это будет больше просто инициализация, а не выделение) как функцию, но подпрограмму также можно использовать. Вы можете использовать интерфейсный блок, как вы это делали, чтобы добиться того же имени, что и имя класса, но вы должны быть последовательными и использовать CALL, если вы определили его как подпрограмму.

В конструкторе производного класса можно было просто установить нужный компонент или использовать конструктор базового класса. Не забудьте тогда написать правильно работающие пользовательские назначения для ваших типов.

person Vladimir F    schedule 14.06.2012
comment
На самом деле, стандарт Fortran 2008 (ну, пункт 4.5.7.2.2 последнего проекта стандарта — ISO/IEC JTC 1/SC 22/WG 5/N1830) гласит: Расширенный тип имеет скалярный, неуказательный , нераспределяемый, родительский компонент с типом и параметрами типа родительского типа. Имя этого компонента является именем родительского типа. что делает ваше первое предложение неверным. У меня нет под рукой стандарта Fortran 2003, но я сомневаюсь, что этот аспект языка изменился между стандартами. Я согласен с общей направленностью остальной части вашего ответа. - person High Performance Mark; 14.06.2012
comment
Спасибо. Может я и читал, но точно забыл. - person Vladimir F; 14.06.2012