【问题标题】:Adding item to list in C++在 C++ 中将项目添加到列表
【发布时间】:2010-01-26 11:43:08
【问题描述】:

我在我的 C++ 应用程序中使用了两个类。代码如下:

class MyMessageBox
{
public:
    void sendMessage(Message *msg, User *recvr);
    Message receiveMessage();
    list<Message> dataMessageList;
};

class User
{
public:
    MyMessageBox *dataMsgBox;
};

msg 是指向 Message 类的派生类对象的指针。我已经实现了函数 sendMessage 如下:

void MyMessageBox::sendMessage(Message *msg, User *recvr)
{
    Message &msgRef = *msg;
    recvr->dataMsgBox->dataMessageList.push_back(msgRef);
}

当我编译这段代码时,我得到以下错误: 未定义对“消息的 vtable”的引用。请帮我解决这个问题。

谢谢, 拉克什。

【问题讨论】:

  • 我使用的是 GCC 编译器 gcc 4
  • Message类的实现是什么?此外,由于您使用的是 std::list,一旦您将它们 push_back 放到列表中,您的派生 Message 对象将被切片为纯 Message 对象。改为使用列表
  • 为了让我们帮助您,您需要添加文件的所有内容。您刚刚显示的内容应该没有错误。

标签: c++ templates pointers reference libstdc++


【解决方案1】:

我不知道你想用那个 msgRef 做什么,但它是错误的。您是一名前 Java 程序员吗?

如果MessageMessage 派生类的基类,则需要将指针存储在列表中。将list&lt;Message&gt;更改为list&lt;Message*&gt;;并且push_back(msgRef) 应该变成push_back(msg),完全删除msgRef 代码。

此外,就风格而言,将大量 -&gt; 运算符链接在一起是个坏主意。在这种情况下,最好在User 上实现一个方法,将Message 添加到它自己的列表中并调用它。

【讨论】:

  • 感谢凯洛坦。我按照你说的修改了代码,现在可以正常编译了。
  • @Rakesh K - 如果你有一个列表,不要忘记你需要额外的列表清理代码。列表析构函数将删除指针指向的元素。您必须自己手动删除它们,或者(推荐)使用 boost::shared_ptr 之类的东西将它们作为值对象处理,这些对象在对它们的最后引用被销毁时被销毁。如果您不使用 shared_ptr 或自己清理列表,您将最终导致资源泄漏。
【解决方案2】:

首先,如果您想在标准 C++ 容器中存储多态对象,您应该存储指向该对象的指针,而不是基类的对象。如果不这样做,就会遇到对象切片问题。另外,帮自己一个忙,将指针包装在智能指针中以防止资源泄漏 - 我建议 boost::shared_ptr.

鉴于您尚未向我们展示 Message 的代码,我们只能猜测问题所在。由于它指的是 vtable,因此很有可能:

  • 您没有将 Message 的任何类成员声明为 virtual。从析构函数开始是个好主意
  • 您忘记链接包含已编译的 Message 代码的目标文件

顺便说一句,在sendMessage() 中创建附加引用不是必需的,恕我直言,这并不完全有助于提高可读性。只需在调用 push_back() 时取消引用 msg 指针即可。

【讨论】:

    【解决方案3】:

    如果要处理子类消息,则需要使用消息指针列表而不是消息对象,并管理它们的生命周期。为方便起见,我建议制作它

    list< boost::shared_ptr<Message> > datamessageList
    

    使用boost 库。 (不要冒犯,但你确实需要阅读更多关于 C++ 和指针的内容:看起来你尝试了代码的各种排列,直到你得到编译的东西......)

    【讨论】:

      【解决方案4】:

      我认为这是一条略微做作的错误消息,表明您尚未为消息类实现构造函数。看看herehere on SO...

      鉴于您试图将指针传递给对象列表,编译器可能会抱怨它无法将Message* 转换为Message。尝试按照 Kylotan 的建议将您的列表更改为 Message* 列表。

      是编译错误还是链接错误?

      【讨论】:

      • 在这种情况下不是。没有充分的理由在这里实现 virtual 构造函数。
      【解决方案5】:

      因为有些人提出了更好的解决方案:查看 std::queue 或 std::deque 来对您的消息进行排队。所以现在你有:

      std::queue<std::tr1::shared_ptr<Message> > dataMessageQueue;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-06-23
        • 1970-01-01
        • 2013-05-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多