2013-09-18 2 views
1

Я должен реализовать свой собственный список с stl для моего класса структур данных, вот код, который у меня есть.Stl List Iterator Error

Playlist.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 */ 

Playlist.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; 
} 

Когда я пытаюсь скомпилировать это я получаю:

ошибки: преобразование из «станд :: Список :: const_iterator { aka std :: _ List_const_iterator} 'для нескалярного типа' std :: list :: iterator {aka std :: _ List_iterator} 'запрошен

в обоих местах, отмеченных в коде.

ответ

1

Метод void Playlist::print(ostream& out) const обозначается Уст. Таким образом, plist равен const, и поэтому plist.begin() возвращает const_iterator. Вам придется либо удалить const из метода, использовать const_cast (худшее решение), либо просто использовать const_iterator для перебора по списку (лучший вариант).

+0

после удаления const из метода, который он скомпилировал. благодаря – user2325753

1

Использование list<Song>::const_iterator itr = plist.begin();

Вы объявляете метод как const который помечает объект, на котором она исполняется как константы. Поэтому вам не следует изменять членов. Но регулярный iterator позволяет изменять объект, на который он ссылается. С этой целью был создан const_iterator - он работает аналогичным образом, но у вас нет возможности изменять объект, на который он указывает.

EDIT 2 Вы можете удалить const из метода, и было бы обобщать, но это плохая идея - ваш метод поиска, он не изменяет содержимое объекта, и поэтому интерфейс следует указать, что в явном виде.

+2

использование немного больше подробно пожалуйста? Я хотел бы знать, почему –

+0

@ Gmercer015, пожалуйста, посмотрите 2 изменения ... – gt6989b

0

Если вы находитесь в методе const, вы можете вызвать только метод begin, возвращающий const_iterator, поэтому вы должны использовать их вместо простых итераторов.

2

Ваш метод отмечен как const (т. Е. Он не имеет права изменять переменные экземпляра), но вы получаете доступ к своему списку с итератором, который не помечен как const, и, вернув его, например, вы можете изменить экземпляр переменной и разбить ключевое слово «const» этого метода.

Надежда, что Im ясно

0

В обоих случаях вы вызываете версию const List::begin(), которые возвращают List::const_iterator.

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

должен устранить проблему, но тогда вам понадобится подпись ваших методов для возврата const_iterator.

0

Ну, это то, о чем говорится в сообщении об ошибке.

Это был вы, который объявил Playlist::print как метод const. Это немедленно означает, что внутри этого метода все члены класса теперь имеют типы const. Ваш plist будет иметь тип const list<Song> внутри Playlist::print. Методы begin()/end() контейнеров const возвращают const_iterator для этих контейнеров.Вы не можете инициализировать/назначить iterator с помощью const_iterator. Вот что говорит вам компилятор.

Либо переключитесь на const_iterator внутри этих методов, либо прекратите объявлять эти методы const.

В случае Playlist::print ответ очевиден: просто переключитесь на const_iterator.

В случае Playlist::find это может быть другая история. Это вопрос ваших намерений. Если вы просто переключитесь на const_iterator внутри Playlist::find, вам нужно будет вернуть const_iterator. Это работает для вас? Но если вы хотите изменить плейлист извне через возвращенный итератор, вам, как правило, придется реализовать две версии Playlist::find: константу, возвращающую const_iterator, и неконстантную, возвращающую iterator.