【问题标题】:Cast an object that is pointed by an iterator转换迭代器指向的对象
【发布时间】:2016-04-21 09:48:35
【问题描述】:

我有这个多重集容器:

multiset<IMidiMsgExt, IMidiMsgExtComp> queuedNotes;

IMidiMsgExt 是我自己创建的一个结构(我需要它作为一个附加属性,mTick),它扩展了IMidiMsg

struct IMidiMsgExt : public IMidiMsg
{
    IMidiMsgExt() {
    }

    double mTick = 0.;

    void IMidiMsgExt::MakeNoteOnMsg(int noteNumber, int velocity, int offset, double tick, int channel)
    {
        Clear();
        mStatus = channel | (kNoteOn << 4);
        mData1 = noteNumber;
        mData2 = velocity;
        mOffset = offset;
        mTick = tick;
    }

    void IMidiMsgExt::MakeNoteOffMsg(int noteNumber, int offset, double tick, int channel)
    {
        Clear();
        mStatus = channel | (kNoteOff << 4);
        mData1 = noteNumber;
        mOffset = offset;
        mTick = tick;
    }

    void IMidiMsgExt::Clear()
    {
        mOffset = 0;
        mStatus = mData1 = mData2 = 0;
        mTick = 0.;
    }
};

下一步:我在那个queuedNotes 中存储了一些IMidiMsgExt 对象,其中:

IMidiMsgExt* noteOff = new IMidiMsgExt;
noteOff->MakeNoteOffMsg(57, 0, tickSize * 111, 0);
queuedNotes.insert(*noteOff);

现在,我需要使用一个名为 SendMidiMsg(IMidiMsg* pMsg) 的函数(将 IMidiMsg 类型作为输入)将我的对象 IMidiMsgExt 发送给它。

我从列表中提取第一个对象到迭代器:

auto midiMessage = queuedNotes.begin();

但是当我尝试投射它并使用SendMidiMsg:

SendMidiMsg((IMidiMsgExt*)midiMessage);

上面写着no suitable conversion function from "std::_Tree_const_iterator&lt;std::_Tree_val&lt;std::_Tree_simple_types&lt;IMidiMsgExt&gt;&gt;&gt;" to "IMidiMsg *" exists

我哪里错了?我应该使用dynamic casting吗?

【问题讨论】:

    标签: c++ inheritance casting iterator


    【解决方案1】:
    auto midiMessage = queuedNotes.begin();
    

    midiMessage 的类型为 std::multiset::iterator。它不能转换为您的类型IMidiMsgExt。 Iterator 是一个行为类似于指针的对象,因此您可以使用取消引用运算符 (*) 来获取它“指向”的对象。您也不需要将派生对象强制转换为其基类,这是隐式完成的。您需要做的就是获取迭代器“指向”的地址以获取指向IMidiMsgExt 的指针:

    SendMidiMsg(&*midiMessage);
    

    快速分解&amp;*midiMessage

      variable    -     type
    midiMessage   - std::multiset::iterator
    *midiMessage  - IMidiMsgExt
    &*midiMessage - IMidiMsgExt*
    

    编辑: 关于您的 const_iterator 错误。 std::multiset::begin() is supposed to always return const_iterator。您的函数 SendMidiMsg() 需要一个非 const 指针 - 它表示它想要编辑消息。 multiset 不允许更改元素。

    您可以复制消息,然后致电SendMidiMsg()。如果您不再需要容器内的消息,您也可以在之后将其删除。

    auto msg = *midiMessage;
    SendMidiMsg(&msg);
    queuedNotes.erase(midiMessage);
    

    注意:您的程序似乎存在内存泄漏。您使用 new 创建消息,但我没有看到任何删除、释放内存的调用。

    IMidiMsgExt* noteOff = new IMidiMsgExt;
    noteOff->MakeNoteOffMsg(57, 0, tickSize * 111, 0);
    queuedNotes.insert(*noteOff);
    

    【讨论】:

    • 但它说:argument of type "const IMidiMsgExt *" is incompatible with parameter of type "IMidiMsg *"
    • @paizza 这意味着queuedNotes.begin() 返回一个const_iterator。如果您取消引用 const_iterator,它将返回对该对象的 const 引用。您的 SendMidiMsg() 需要一个非 const 指针。您的程序中有一个概念性错误。您正在尝试修改您说不应该修改的内容。
    • 我无法更改SendMidiMsg(),因为它是我将使用的框架中的一种方法。唯一的方法是更改​​ iterator 返回类型。但也有:我无法编辑multiset 列表。我需要更换容器吗?存储和返回非常量元素的东西?
    • 没有。问题是你为什么会得到const_iterator。您必须有一个对queuedNotes 的常量引用。如果您在致电SendMidiMsg() 之前显示代码,将会有所帮助。有趣的是,在您调用 begin() 之前,您从哪里获得 queuedNotes
    • begin 之前我只是检查一下:while (queuedNotes.size() &gt; 0)。比自动和那个功能。我在 .h 文件中清除 multiset&lt;IMidiMsgExt, IMidiMsgExtComp&gt; queuedNotes;
    猜你喜欢
    • 1970-01-01
    • 2013-02-16
    • 1970-01-01
    • 2016-09-17
    • 2018-05-30
    • 1970-01-01
    • 1970-01-01
    • 2010-10-19
    • 2023-04-04
    相关资源
    最近更新 更多