2005-04-24

À l'heure du super

J'ai enfin mis de quoi colorier du C++ de façon automatique, par conséquent je peux me permettre d'écrire ce petit billet :)

Dans les langages objet, il est souvent intéressant dans une hiérarchie de classes de devoir faire appel aux classes parentes. Par exemple, prenons une classe qui dérive d'une autre, et dotons-la de quoi faire de l'enregistrement et du chargement depuis un fichier.

J'ai ici une classe de fenêtre qui contient une position et une dimension. La fonction Dump permet de stocker l'objet et la fonction Load permet de faire l'inverse :

class Window
{
	int m_nX, m_nY, m_nWidth, m_nHeight;
public:
	virtual void Dump(File& file) const
	{
		file << m_nX << m_nY << m_nWidth << m_nHeight; // Écrit dans le fichier
	}
	virtual void Load(File& file)
	{
		file >> m_nX >> m_nY >> m_nWidth >> m_nHeight; // Lit depuis le fichier
	}
};

Maintenant, je crée une classe plus évoluée qui dérive de la première, et cette fois-ci j'ajoute un nouvel attribut : un titre pour la fenêtre. Je tiens à profiter des fonctions Load et Dump de la classe de base pour qu'elle écrive sa partie dans le fichier. Ça donne ça :

class TitledWindow : public Window
{
	string m_strTitle;
public:
	virtual void Dump(File& file) const
	{
		Window::Dump(file); // Appelle la fonction parente
		file << m_strTitle; // Écrit dans le fichier
	}
	virtual void Load(File& file)
	{
		Window::Load(file); // Appelle la fonction parente
		file >> m_strTitle; // Lit depuis le fichier
	}
};

Au cours du projet, il se peut qu'on souhaite changer le nom d'une classe. Il est fastidieux de devoir passer le code en revue pour changer ce nom. La méthode que j'utilise pour accélérer ce processus est de définir un type local représentant le nom de la classe parente :

class TitledWindow : public Window
{
	typedef Window parent;  // Un terme représentant la classe de base : « parent »
	string m_strTitle;
public:
	virtual void Dump(File& file) const
	{
		parent::Dump(file); // Petite différence ici
		file << m_strTitle;
	}
	virtual void Load(File& file)
	{
		parent::Load(file); // Et là
		file >> m_strTitle;
	}
};

Ainsi, si jamais on décide de donner un autre nom à la classe Window, on n'aura pas à passer en revue tout le code.

Dans les versions récentes du compilateur C++ de Microsoft, ils ont introduit ce concept de façon automatique, un peu comme ce qu'on trouve en Java. Le terme employé est «  __super » ou « super » pour peu qu'on fixe une option de compilation. Voilà une extension intéressante que j'aimerais voir dans le standard C++. On aura alors :

class TitledWindow : public Window
{
	// Plus de typedef ici
	string m_strTitle;
public:
	virtual void Dump(File& file) const
	{
		super::Dump(file); // Et hop
		file << m_strTitle;
	}
	virtual void Load(File& file)
	{
		super::Load(file); // Hopeula
		file >> m_strTitle;
	}
};