我有一个基类,
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);
在重载的 formatOutgoing 方法中,我有类似的内容,
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;
我不明白为什么第二种情况不起作用。还是如何使其最佳运作?
答案 0 :(得分:1)
您正在按值传递指针。该函数将复制您传入的指针,然后修改该副本。这就是为什么在函数调用后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
之类的东西。