返回基类对象中的派生对象指针

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*中。 调用函数应该能够将这个Messageobject提供给外部,而外部只知道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);  

【讨论】:

以上是关于返回基类对象中的派生对象指针的主要内容,如果未能解决你的问题,请参考以下文章

基类指针和派生类指针

基类指针指向派生类对象&派生类指针指向基类对象

派生类和基类的转换

使用基类指针查找派生类对象的大小

使用具有指向派生类对象的指针的基类指针数组调用派生类方法

关于C++基类、派生类的引用和指针