Pour l'exemple, je vais utiliser les classes ci-dessous. Pour plus de simplicité, je les ai laissées dans le même fichier.

class Player
{
public:
	const string name;
 
	inline Player(string name) : name(name) {}
	inline Player(const Player& player) : name(player.name) {}
	inline virtual ~Player(void) {}
};
 
class Players
{
public:
	inline Players(void) {}
	inline Players(const Players& plrs) {}
	inline ~Players(void) {}
 
	void addPlayer(const Player* p) { players[p->name] = p; }
	void removePlayer(const Player* p) { players.erase(p->name); }
 
	const Player* getPlayer(const string name)
	{
		map<const string, const Player*>::iterator it;
		it = players.find(name);
		return (it != players.end()) ? it->second : NULL;
	}
 
private:
	map<const string, const Player*> players;
};

Pour utiliser ces deux classes dans un morceau de code, c'est assez simple :

void test(Players* p);
int main(int argc, char** argv)
{
	Players* p = new Players();
	p->addPlayer(new Player("cedric"));
	p->addPlayer(new Player("captain"));
	p->addPlayer(new Player("chipal"));
 
	test(p);
}
 
void test(Players* p)
{
	const Player* l = p->getPlayer("cedric");
	cout << "Player name : " << l->name << endl;
}

Jusque la, tout va bien le programme compile sans problème ! Maintenant, il arrive souvent que l'on veuille assurer que l'objet reçu en paramètre ne sera pas modifié. Pour cela on utilise le mot-clé const :

void test(const Players* p)
{
	const Player* l = p->getPlayer("cedric");
	cout << "Player name : " << l->name << endl;
}

Et c'est la qu'intervient la première insulte du compilateur (g++ en l'occurence) qui vomit le message suivant :

main.cpp: In function ‘void test(const Players*)’:
main.cpp:58: error: passing ‘const Players’ as ‘this’ argument of ‘const Player* Players::getPlayer(std::string)’ discards qualifiers

En clair, il ne peut pas assurer à la compilation que l'instance Players reçue en paramètre ne sera pas modifiée. Afin de corriger ce problème, il suffit de déclarer la méthode getPlayer comme étant constante (elle ne modifie pas l'instance sur laquelle elle travaille).

const Player* getPlayer(const string name) const
{
	map<const string, const Player*>::iterator it;
	it = players.find(name);
	return (it != players.end()) ? it->second : NULL;
}

Hop ! Recompilation !

main.cpp: In member function ‘const Player* Players::getPlayer(std::string) const’:
main.cpp:38: error: no match for ‘operator=’ in ‘it = ((const Players*)this)->Players::players.std::map<_Key, _Tp, _Compare, _Alloc>::find [with _Key = const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, _Tp = const Player*, _Compare = std::less<const std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, _Alloc = std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, const Player*> >](((const std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)(& name)))’
/usr/lib/gcc/i686-pc-linux-gnu/4.4.3/include/g++-v4/bits/stl_tree.h:154: note: candidates are: std::_Rb_tree_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, const Player*> >& std::_Rb_tree_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, const Player*> >::operator=(const std::_Rb_tree_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, const Player*> >&)

C'est ici que les choses se corsent... visiblement il n'aime pas la ligne it = players.find(name). Gcc semble vouloir donner quelques indication en affichant un énorme message d'erreur pour le moins obscur.

Heureusement, la solution est assez simple ! C'est toujours lié au fait que le typage doit assurer au compilateur que la méthode ne modifie en rien l'objet courant (et récursivement à travers les objets utilisés dans ces méthodes). Pour ce cas, la classe map, fournit un itérateur constant :

const Player* getPlayer(const string name) const
{
	map<const string, const Player*>::const_iterator it;
	it = players.find(name);
	return (it != players.end()) ? it->second : NULL;
}