1

我必须用 stl 为我的数据结构类实现我自己的列表,这是我拥有的代码。

播放列表.h

#ifndef PLAYLIST_H
#define PLAYLIST_H

#include <iostream>
using std::ostream;

#include <list>
using std::list;

class Song;

class Playlist
{
public:
    void append(const char* name, const char* artist);
    list<Song>::iterator find(const char* name) const;
    void delete_song(const char* name);
    void print(ostream& out) const;

private:
    list<Song> plist;
};

ostream& operator << (ostream& out, const Playlist& playlist);

#endif  /* PLAYLIST_H */


ostream& operator << (ostream& out, const Playlist& playlist);

#endif  /* PLAYLIST_H */

播放列表.cpp

#include <iostream>
using std::ostream;
using std::endl;

#include <cstring>

#include "Song.h"
#include "Playlist.h"

void Playlist::append(const char* name, const char* artist)
{
    Song song(name, artist);
    plist.push_back(song);
}

list<Song>::iterator Playlist::find(const char* name) const
{
    list<Song>::iterator itr = plist.begin(); // error occurs here
    while(itr != plist.end() && strcmp(itr->get_name(), name) == 0)
    {
        itr++;
    } 

    return itr;
}

void Playlist::delete_song(const char* name)
{
    list<Song>::iterator itr = find(name);
    if (itr != plist.end())
        plist.erase(itr);
}

void Playlist::print(ostream& out) const
{
    list<Song>::iterator itr = plist.begin(); // error occurs here
    while (itr != plist.end())
    {
       out << *itr << endl;
       itr++;
    }
} 

ostream& operator << (ostream& out, const Playlist& playlist)
{
    playlist.print(out);
    return out;
}

当我尝试编译它时,我得到:

错误:请求从 'std::list::const_iterator {aka std::_List_const_iterator}' 转换为非标量类型 'std::list::iterator {aka std::_List_iterator}'

在代码中标记的两个地方。

4

6 回答 6

2

方法void Playlist::print(ostream& out) const被指定为 const。因此 plist 是const,所以plist.begin()返回 a const_iterator。您要么必须从方法中删除 const,使用 const_cast(最差解决方案),要么只需使用 const_iterator 来迭代列表(最佳选项)。

于 2013-09-18T15:46:51.067 回答
1

利用list<Song>::const_iterator itr = plist.begin();

您正在声明该方法,该方法将const其正在执行的对象标记为 const。所以你不应该被允许改变成员。但是常规iterator允许更改它引用的对象。为此目的,const_iterator创建了 - 它的工作方式类似,但您无法更改它指向的对象。

编辑 2 您可以const从方法中删除它并且它会编译,但这是一个坏主意 - 您的方法是查找方法,它不会更改对象内容,因此接口应该明确指出。

于 2013-09-18T15:46:06.073 回答
1

您的方法被标记为 const (即它无权修改实例变量),但是您使用未标记为 const 的迭代器访问您的列表;例如,通过返回它,您可以修改实例变量并中断方法的“const”关键字。

希望我清楚

于 2013-09-18T15:46:26.777 回答
0

如果你在一个 const 方法中,你只能调用 begin 方法返回一个 const_iterator,所以你应该使用那些而不是简单的迭代器。

于 2013-09-18T15:46:20.997 回答
0

在这两个地方,您都在调用 的 const 版本List::begin(),它返回List::const_iterator

list<Song>::const_iterator itr = plist.begin();

应该可以解决问题,但是您需要方法的签名才能返回 const_iterator。

于 2013-09-18T15:47:06.347 回答
0

好吧,这就是错误消息所说的。

是您声明Playlist::printconst该类的方法。这立即意味着在该方法内所有类成员现在都有const类型。您plist将在const list<Song>里面输入类型Playlist::print。const 容器的方法begin()/为这些容器返回。您不能使用. 这就是编译器告诉你的。end()const_iteratoriteratorconst_iterator

要么切换到const_iterator这些方法内部,要么停止声明这些方法const

如果Playlist::print答案很明显:只需切换到const_iterator.

万一Playlist::find它可能是一个不同的故事。这是你的意图问题。如果你只是切换到const_iteratorinside Playlist::find,你将不得不const_iterator从它返回。那对你有用吗?但是,如果您希望能够通过返回的迭代器从外部修改播放列表,您通常必须实现两个版本Playlist::find:一个 const 版本,returningconst_iterator和一个非 const 版本,returning iterator

于 2013-09-18T16:00:41.690 回答