返回基类对象中的派生对象指针
Posted
技术标签:
【中文标题】返回基类对象中的派生对象指针【英文标题】:Return derived object pointer in base class object 【发布时间】:2014-06-12 13:31:40 【问题描述】:我有以下问题,我不知道为什么这不起作用。编译器不会产生任何错误,但是当我执行代码时,它会崩溃。
我有一个基类 Message 和一个派生类 MessageA。
class Message
protected:
Message()
public:
virtual ~Message()
virtual void setType(int type) = 0;
virtual int getType() = 0;
protected:
int type;
;
class MessageA : public Message
public:
MessageA(const uint32_t cid);
MessageA();
~CanMessage();
void setCID(const uint32_t cid);
void setType(int type);
int getType();
uint32_t getCID();
private:
uint32_t cid;
;
为了灵活,我将提供哪种消息作为函数的参数接收我选择的参数类型 Message* 消息。
bool ReceiveSingle(Message* message)
message = new MessageA(0x53);
return true;
该函数在另一个函数中调用,该函数应该对返回的指针执行操作:
Message* temp_message; //Global variable
/*
....
*/
ReceiveSingle(temp_message)
MessageA* temp = static_cast<MessageA*>(temp_message);
int cid = temp->getCID(); // This operation does not work !!!!!
所以我想保持ReceiveSingle
的参数灵活并选择基类类型Message*。该函数本身创建一个派生对象指针,并应通过全局基础对象指针temp_message*
返回它。稍后应该可以访问派生对象的变量。静态演员有效,但是当我执行getCID()
te 程序崩溃。我找不到任何解决此错误的方法。
如果有人可以帮助我,那就太好了!
非常感谢!!
【问题讨论】:
我不确定您的ReceiveSingle
函数的语法是否正确。您没有返回类型,也没有为 temp_message 指定类型(这将覆盖全局 temp_message 变量)...根据您的编译器,它们可能分别默认为 void 和 int。
@Majenko 提示:那是一个函数调用。
是吗?它看起来不像我的函数调用。终结点在哪里; ...?为什么后面有 和 ?为什么和全局变量定义在同一个作用域?
@Majenko 我很确定它应该是(考虑到声明就在上面)。
和
用于声明嵌套范围块。
很抱歉 和 错了,在 ReceiveSingle(temp_message) 之后应该是 ;
【参考方案1】:
根据您分配给 temp_message 的内容,它可能只是一条消息而不是消息 A。 使用 dynamic_cast 而不是 static_cast 并且检查它的 temp 是否为 nullptr/NULL。如果为 NULL,则 temp_message 是 Message 而不是 MessageA。
【讨论】:
我总是将派生对象分配给 temp_message。所以永远不要 Message,但总是 MessageA 或 MessageB 等等。【参考方案2】:考虑到您要静态地 转换指针,您并不会真正利用动态多态性。
我的建议是改用静态多态性:
template<class Type>
auto func(const Type& t)
int cid = t.getCID();
// ...
然后在外部使用std::unique_ptr
(或任何其他智能指针):
auto message = std::unique_ptr<MessageA>(new MessageA(0x53));
auto ret = func(*message);
原来的问题是:
bool ReceiveSingle(Message* message)
message = new MessageA(0x53);
return true;
并没有真正修改传递的指针。快速修复:
bool ReceiveSingle(Message*& message)
// ^
message = new MessageA(0x53);
return true;
但这是一个糟糕的主意,主要是因为您使用的是裸指针。
【讨论】:
那么消息是函数ReceiveSingle(Message* message)
的参数吗?提供ReceiveSingle()
的类实现了一个接口,以便为不同的派生消息类型提供ReceiveSingle()
的不同实现。实际调用ReceiveSingle()
的方法不需要处理哪种派生消息。因此调用ReceiveSingle()
的函数应该通过参数向函数提供一个Message*对象。 ReceiveSingle()
应该创建一个派生消息并将其存储在提供的参数Message*
中。
调用函数应该能够将这个Message
object提供给外部,而外部只知道message*
object中包含的是哪个派生类型。
我希望这有助于理解我试图实现的目标;)【参考方案3】:
我找到了一个快速有效的解决方案:
ReceiveSingle(Message** message)
MessageA* new_message = new MessageA(0x53);
*message = new_message;
return true;
为了调用ReceiveSingle(Message** message)
和Message* temp_message
使用
ReceiveSingle(&temp_message);
然后要访问存储在 temp_message 中的 MessageA 对象,请使用静态转换:
MessageA* tempA = static_cast<MessageA*>(temp_message);
【讨论】:
以上是关于返回基类对象中的派生对象指针的主要内容,如果未能解决你的问题,请参考以下文章