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



我有一个基类,

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;
}

其中CustomMsgHandler 是从 MsgHandler类继承而来的,一切都很好。这就是我猜多态性的整个想法。可以将派生类的对象传递给接受指向基类的指针的接口。


不起作用的是,恰恰相反。其中parseIncoming((执行以下操作,

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读取,则在调用parseIncoming消息后,我没有得到"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;

我不明白为什么第二种情况不起作用。或者如何最好地使其发挥作用?

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

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

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

另请注意,您首先在main中执行动态分配。

MsgFormat* pBaseMsg = new pBaseMsg();

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

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

在这里你忘了先delete指针,所以你泄露了内存。每次调用new都需要调用delete以释放内存。(除非它传递给智能指针的构造函数之类的东西,否则智能指针将为您处理delete

当使用 c++11 或 boost 等效项时,
在现代C++中确实没有必要使用裸newdelete。您应该改用诸如std::vectorstd::unique_ptrstd::shared_ptr之类的东西。

相关内容

  • 没有找到相关文章

最新更新