我有一个基类,
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++中确实没有必要使用裸new
和delete
。您应该改用诸如std::vector
、std::unique_ptr
和std::shared_ptr
之类的东西。