跳转至内容
  • 版块
  • 最新
  • 标签
  • 热门
  • Online Tools
  • 用户
  • 群组
折叠
品牌标识

D2Learn Forums

  1. 主页
  2. General Discussion | 综合讨论
  3. 项目中智能指针多态性丢失的问题

项目中智能指针多态性丢失的问题

已定时 已固定 已锁定 已移动 General Discussion | 综合讨论
c++面向对象接口设计
7 帖子 2 发布者 134 浏览
  • 从旧到新
  • 从新到旧
  • 最多赞同
登录后回复
此主题已被删除。只有拥有主题管理权限的用户可以查看。
  • FrozenLemonTeeF 离线
    FrozenLemonTeeF 离线
    FrozenLemonTee
    写于 最后由 编辑
    #1

    项目地址:https://github.com/FrozenLemonTee/original
    是一个仿STL的工具库项目。

    问题源自于transform和transformStream两个类的设计上。transform是一个接口,通过继承这个类并且实现apply方法,可以直接以仿函数的方式调用这个类,将定义好的变换施加给项目中继承了iterable接口的可迭代对象中存放的所有元素。transformStream是一个中间的临时类,同时和transform一样也是可调用类,用于对若干个传入函数的transform所构成的复合调用链进行管理,在自己被调用时按照调用链顺序依次调用相关的transform以达到复合调用的目的。复合调用链用+操作符进行连接,通过重载+操作符自动生成transformStream,并将调用链中的transform加入生成的transformStream的管理。

    在测试中发现,传入函数的复合调用链的每个transform派生类对象在被调用时,调用的是基类的apply方法,而基类定义的是空操作,也就导致整个调用链被调用时不施加任何变换。经过检查是transformStream的pushEnd方法存在问题:

        template<typename TYPE>
        void original::transformStream<TYPE>::pushEnd(const transform<TYPE>& t) {
            this->stream.pushEnd(std::make_shared<std::decay_t<decltype(t)>>(t));
        }
    

    当以智能指针将传入的transform包装时,智能指针的参数无法获得传入的对象t正确的派生类型,导致对象t以基类的形式被存储。

    我尝试了很多方案想要解决这个问题,一开始怀疑是自定义的容器chain的问题,于是换成std::vector,或者考虑以std::function的方式存储变换,但是都无效,想请教一下如何设计可以避免这个问题?

    sunrisepeakS 2 条回复 最后回复
    0
    • FrozenLemonTeeF 离线
      FrozenLemonTeeF 离线
      FrozenLemonTee
      写于 最后由 编辑
      #2

      相关测试的例子在项目的test/test2.cpp中,最后几行就是针对该问题的测试

      1 条回复 最后回复
      0
      • sunrisepeakS 离线
        sunrisepeakS 离线
        sunrisepeak d2learn-dev
        在 回复了 FrozenLemonTee 最后由 编辑
        #3

        @FrozenLemonTee 在 项目中智能指针多态性丢失的问题 中说:

        make_shared

        如果传近来的是个const, 用make_shared创建对象的时候使用decay_t导致创建的就是基类对象了, 应该直接创建t的原类型, 向上转型自动会做

        1 条回复 最后回复
        0
        • FrozenLemonTeeF 离线
          FrozenLemonTeeF 离线
          FrozenLemonTee
          写于 最后由 编辑
          #4

          可以具体说一下怎么做吗

          sunrisepeakS 1 条回复 最后回复
          0
          • sunrisepeakS 离线
            sunrisepeakS 离线
            sunrisepeak d2learn-dev
            在 回复了 FrozenLemonTee 最后由 编辑
            #5

            @FrozenLemonTee 在 项目中智能指针多态性丢失的问题 中说:

            智能指针的参数无法获得传入的对象t正确的派生类型,导致对象t以基类的形式被存储。

            发现你已经清楚是这个问题了, 对于涉及避免就是可能有两个简单的解决方法

            • 1 想办法拿到真实类型, 如果过程中要重新创建对象
            • 2 通过外部创建准确对象 然后 传递过程move指针
            1 条回复 最后回复
            0
            • sunrisepeakS 离线
              sunrisepeakS 离线
              sunrisepeak d2learn-dev
              在 回复了 FrozenLemonTee 最后由 编辑
              #6

              @FrozenLemonTee 避免创建对象, 如果必须创建 可以在最容易获取原对象的地方创建对象然后move

              1 条回复 最后回复
              0
              • FrozenLemonTeeF 离线
                FrozenLemonTeeF 离线
                FrozenLemonTee
                写于 最后由 编辑
                #7

                已完成。
                最终解决方案是,通过cloneable接口的clone方法,实现具体类对象的动态创建:
                https://github.com/FrozenLemonTee/original/commit/fe14776ccc411790084dcd4ea1a002d3ee22eaa7
                https://github.com/FrozenLemonTee/original/commit/cdd94d92c29c09bb58ca4d6f4b9eadb8272e7e27

                1 条回复 最后回复
                1

                • 登录

                • 没有帐号? 注册

                • 登录或注册以进行搜索。
                d2learn forums Powered by NodeBB
                • 第一个帖子
                  最后一个帖子
                0
                • 版块
                • 最新
                • 标签
                • 热门
                • Online Tools
                • 用户
                • 群组