代码之家  ›  专栏  ›  技术社区  ›  Duck Dodgers

将派生对象分配给函数内部的基类指针

  •  0
  • Duck Dodgers  · 技术社区  · 6 年前

    我有一个基类,

      struct MsgFormat {
        MsgFormat();
        virtual ~MsgFormat();
    
        const std::string rootNode;
      };
    

    一个派生类,

     class ServiceMsg : public MsgFormat {
      public:    
        explicit ServiceMsg(std::string A, std::string B);
        ServiceMsg();
        ServiceMsg(const ServiceMsg& srvMsg);
        class ServiceMsg& operator=(const ServiceMsg& srvMsg);
        ~ServiceMsg();
    
        std::string A() const;
        std::string B() const;
    
      private:
        std::string m_A;
        std::string m_B;
    };
    

    现在我有了一个消息处理程序类,它接受一个指向基类的指针,如下所示,

      class MsgHandler
      {
      public:
        MsgHandler();
        virtual ~MsgHandler();
    
        virtual int parseIncoming(struct MsgFormat* pBaseMsg) = 0;
        virtual int formatOutgoing(const struct HermesMsgFormat* const pBaseMsg) = 0;
      };
    

    };

    现在,如果我在main()中这样做,

    ServiceMsg* pSrvMsg = new ServiceMsg("foo", "bar");    
    SpecificMsgHandler m_handle->formatOutgoing(pSrvMsg);
    

    在超载的内部 格式化输出 方法,我有这样的东西,

    virtual int CustomMsgHandler::formatOutgoing(const struct MsgFormat* const pBaseMsg)
    {
        const ServiceMsg* const pServiceMsg = dynamic_cast<const ServiceMsg* const>(pBaseMsg);
        std::cout << pServiceMsg->A() << std::endl;
        std::cout << pServiceMsg->B() << std::endl;
    }
    

    在哪里? 客户Ghandler 是从 甘德勒女士 同学们,一切都很好。这就是多态性的全部概念。可以将派生类的对象传递给接受基类指针的接口。


    不起作用的恰恰相反。在哪里? 解析传入() 执行以下操作,

        virtual int CustomMsgHandler::parseIncoming(struct MsgFormat* pBaseMsg)
        {
           pBaseMsg = new ServiceMsg("bla", "baa");
    
    #ifdef NDEBUG
           ServiceMsg* pServiceMsg = dynamic_cast<ServiceMsg*>(pBaseMsg);
            std::cout << pServiceMsg->A() << std::endl;
            std::cout << pServiceMsg->B() << std::endl;
            std::cout << "all good here" << std::endl;
    #endif
        }
    

    我在main()中执行以下操作。

    MsgFormat* pBaseMsg = new pBaseMsg();
    SpecificMsgHandler m_handle->parseIncoming(pBaseMsg);
    

    但是如果我试图从main()中的pbasemsg读取,则在从调用返回到 解析传入 留言,我没听到“bla”和“baa”。我得到默认构造函数中设置的内容。

    ServiceMsg* pServiceMsg = dynamic_cast<ServiceMsg*>(pBaseMsg);
    std::cout << pServiceMsg->A() << std::endl;
    std::cout << pServiceMsg->B() << std::endl;
    std::cout << "all good here" << std::endl;
    

    我不明白为什么第二个案子行不通。或者怎样才能最好地发挥作用?

    1 回复  |  直到 6 年前
        1
  •  1
  •   super    6 年前

    您正在按值传递指针。函数将复制传入的指针,然后修改该副本。这就是为什么在 main 在函数调用之后。

    若要解决此问题,可以改为通过引用传递指针,方法是更改函数的签名。

    virtual int CustomMsgHandler::parseIncoming(struct MsgFormat*& pBaseMsg) //added &, it's now a reference to a pointer.
    

    还要注意,您首先要在 主要的 是的。

    MsgFormat* pBaseMsg = new pBaseMsg();
    

    然后将此指针传递给函数并再次执行动态分配。

    pBaseMsg = new ServiceMsg("bla", "baa");
    

    你忘了 delete 首先是指针,所以你泄露了内存。每次呼叫 new 需要打电话给 删除 去释放记忆。(除非它被传递给智能指针的构造函数,否则智能指针将处理 删除 为你祈祷。)

    当使用c++11或boost等价物时
    真的没必要用裸体 新的 删除 在现代C++中。你应该用像 std::vector 我是说, std::unique_ptr std::shared_ptr 是的。