Fortran Coder

查看: 6447|回复: 2
打印 上一主题 下一主题

[讨论] 多态指针问题

[复制链接]

143

帖子

41

主题

1

精华

宗师

F 币
1250 元
贡献
624 点
跳转到指定楼层
楼主
发表于 2019-8-3 21:56:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 weixing1531 于 2019-8-4 13:04 编辑

举个例子:
[Fortran] 纯文本查看 复制代码
module super_class !父类
    implicit none
    private
    public::point

    type::point !父类 
        real::x=0.0
        real::y=0.0
    contains
        procedure,pass(me)::point_new   !构造方法
        procedure,pass(me)::point_print !打印实例变量
        procedure,pass(me)::add 
        procedure,pass(me)::an
        generic::assignment(=) => an  !重载=
        generic::operator(+)   => add !重载+
    end type point
contains
    subroutine point_new(me,x,y) !父类构造方法
        class(point),intent(inout)::me
        real,intent(in)::x
        real,intent(in)::y

        me%x=x
        me%y=y
    end subroutine point_new

    subroutine point_print(me)
        class(point),intent(in)::me

        write(*,*)'x=',me%x,'y=',me%y
    end subroutine point_print

    subroutine an(me,p) !父类赋值运算
        class(point),intent(out)::me
        class(point),intent(in)::p

        me%x=p%x
        me%y=p%y
    end subroutine an

    function add(me,p) !父类加法运算
        class(point),intent(in)::me
        class(point),intent(in)::p
        class(point),pointer::add !返回类型为多态指针

        allocate(point::add) !多态指针分配父类内存
        add%x=me%x+p%x
        add%y=me%y+p%y
    end function add
end module super_class

module sub_class !子类
    use super_class
    implicit none
    private
    public::point3d

    type,extends(point)::point3d 
        real::z=0.0
    contains
        procedure,pass(me)::point_print !重写父类方法
        procedure,pass(me)::point3d_new !子类构造方法
        procedure,pass(me)::add !重写父类方法
        procedure,pass(me)::an  !重写父类方法
    end type point3d
contains
    subroutine point3d_new(me,x,y,z) !子类构造方法
        class(point3d),intent(inout)::me
        real,intent(in)::x
        real,intent(in)::y
        real,intent(in)::z
        !子类调用父类构造方法
        me%x=x;me%y=y !等价于call me%point%point_new(x,y)
        me%z=z
    end subroutine point3d_new

    subroutine point_print(me) !重写父类方法
        class(point3d),intent(in)::me

        write(*,*)'x=',me%x,'y=',me%y,'z=',me%z
    end subroutine point_print

    function add(me,p) !重写父类方法
        class(point3d),intent(in)::me
        class(point),intent(in)::p
        class(point),pointer::add !返回类型为多态指针
        type(point)::a
        type(point3d)::b

        allocate(point3d::add) !多态指针分配子类内存
        write(*,*)SAME_TYPE_AS(add,b),SAME_TYPE_AS(add,a)
        add%x=me%x+p%x
        add%y=me%y+p%y

        select type(add)
        type is(point3d)
            !一般情况下p%z不可访问
            select type(p) !可绕过上述限制
            type is(point3d)
                add%z=me%z+p%z !父类访问子类成员变量
            end select
        end select
    end function add

    subroutine an(me,p)
        class(point3d),intent(out)::me
        class(point),intent(in)::p

        me%x=p%x
        me%y=p%y
        !一般情况下p%z不可访问
        select type(p) !可绕过上述限制
        type is(point3d)
            me%z=p%z !父类访问子类成员变量
        end select
    end subroutine an
end module sub_class

program main !主程序
    use super_class
    use sub_class
    implicit none

    type(point)::b,d
    type(point3d)::a,c

    call b%point_new(1.0,1.0)
    call b%point_print()
    call d%point_new(3.0,3.0)
    call d%point_print()

    b=b+d !相当于b=b%add(d)
    call b%point_print()

    call a%point3d_new(1.0,1.0,1.0)
    call a%point_print()
    call c%point3d_new(3.0,3.0,3.0)
    call c%point_print()

    a=a+c !相当于a=a%add(c)
    call a%point_print()
    write(*,*)EXTENDS_TYPE_OF(a,b)
end program main


在module sub_class内函数function add中
这段代码中
allocate(point3d::add)
经过write(*,*)SAME_TYPE_AS(add,b),SAME_TYPE_AS(add,a)验证
此时add类型确实是point3d
为何还要用select type对add的类型进行判断?
是不是add的定义class(point),pointer::add规定父类指针访问子类成员变量必须要用select type?





分享到:  微信微信
收藏收藏 点赞点赞 点踩点踩

834

帖子

2

主题

0

精华

大宗师

F 币
3922 元
贡献
2332 点
沙发
发表于 2019-8-5 22:06:10 | 只看该作者
1、为何还要用select type对add的类型进行判断?
我认为这句是多于的。就实际来看,仅需判断P的类型。

490

帖子

4

主题

0

精华

大宗师

F 币
3298 元
贡献
1948 点

水王勋章元老勋章热心勋章

板凳
发表于 2019-8-5 22:39:59 | 只看该作者
直接参考帮助文档的示例不管用?
https://software.intel.com/en-us ... ference-select-type
btw,希望事半功倍的学习OOP还是换python吧
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

捐赠本站|Archiver|关于我们 About Us|小黑屋|Fcode ( 京ICP备18005632-2号 )

GMT+8, 2024-11-1 07:12

Powered by Tencent X3.4

© 2013-2024 Tencent

快速回复 返回顶部 返回列表