Main menu:

Site search

Categories

septembre 2025
L M M J V S D
1234567
891011121314
15161718192021
22232425262728
2930  

Archive

C++ – Classes et fonctions amies

On utilise la notion d’ami lorsque l’on a deux classes dont l’une doit avoir accès aux données membres privées de l’autre.
Cette façon de faire permet de limiter à une seule classe l’accès à des données privées et de ne pas devoir rendre celles-ci publiques ce qui les rendrait disponibles pour tout objet ou classe.

class A
{
  public:
    void f();
};

class B
{
  private:
    friend class A;
    int g(){return x;}
    int x;
};

Il est important de remarquer que c’est la classe qui veut partager ses données privées avec une autre qui donne l’accès à celles-ci en spécifiant que l’autre classe est une amie.
Cela se fait avec le mot-clé friend suivi de la classe qui reçoit l’accès aux données privées.
Les bonnes pratiques de la programmation veulent que même si dans ce cas-ci, A a accès à x dans B, A n’y fasse appel que via une fonction privée g(), qui sert d’interface, et non directement. Rien ne l’empêche néanmoins si ce n’est le code de bonne pratique.

En réalité, cette notion de classe amie est une généralisation des fonctions amies. On peut très bien avoir une fonction membre d’une classe ou une fonction globale à laquelle une classe accorderait l’accès à ses données privées. Le principe est le même que pour une classe.

class A
{
  public:
    int f();

class B
{
  private:
    friend int global_func();
    friend void A::f();
    int x;
};

int A::f()
{
  B b;
  return b.x;
}

int global_func()
{
  B b;
  return b.x;
}

Notez également que les déclarations d’amis peuvent être faites tant dans la partie privée que publique de la classe. Il n’y a aucune différence entre les deux.

Quelques commandes

Voici quelques commandes moins connues mais néanmoins utiles dont je me sers à l’occasion:

Affichage en hexadécimal du contenu d’un fichier

$ od -x filename
$ xxd filename

Cette dernière commande a ma préférence parce qu’elle affiche de manière classique le caractère correspondant au code ASCII et permet d’utiliser grep pour rechercher une chaîne de caractères dans un fichier binaire par exemple. Parfois très utile pour ceux qui font de la programmation.
Par contre l’emploi de la commande od permet le choix de la base (décimal, octal, hexadécimal ou même ASCII).

Affichage du type d’un fichier d’un fichier

Cette commande affiche des renseignements sur le type du fichier contenu dans le fichier. Autrement dit, elle vous dit si le fichier est du type texte, data, image jpg ou autre, audio, vidéo… Très utile parfois. Il ne faut pas perdre de vue que sous Linux, l’extension dans le nom de fichier est facultative et si vous avez un répertoire rempli de fichiers dont vous ignorez le type, cette commande peut vous aider et vous faire gagner pas mal de temps.

$ file filename
$ file *

La commande file avec un * comme argument affiche le type de tous les fichiers ou répertoires (un répertoire est un fichier sous Linux) du répertoire courant.

Compter le nombre de mots ou de lignes dans un fichier

$ wc -l filename
$ wc -w filename

La première commande compte le nombre de lignes, la seconde, le nombre de mots.

Savoir qui est loggé sur une machine

$ w
$ who

Savoir qui s’est loggé sur une machine et quand

$ last
$ last -10

La commande last lit le fichier /var/log/wtmp qui contient les renseignements qu’on recherche. Attention cependant, ce fichier est remis à zéro à chaque reboot de la machine.

Dans tous les cas, n’oubliez pas de consulter la page de manuel de la commande.

KeyStatus

KeyStatus
KeyStatus est un petit programme écrit en python qui permet de monitorer et d’afficher l’utilisation des boutons de la souris, des touches spéciales Ctrl, Alt et Shift et des autres touches du clavier.

Il peut vraiment être utile lorsque vous faites une présentation d’un logiciel en affichant en permanence les touches du clavier et de la souris que vous utilisez.
Pas d’installation compliquée, il vous suffit de le télécharger à cette adresse et de le décompresser là ou vous le désirez. Ensuite, rendez-vous dans le dossier où vous avez décompressé le programme et faites la petite modification suivante au code source pour qu’il soit utilisable avec ubuntu:

$ cd le_répertoire_où_le_fichier_est_décompressé
$ gedit key-status

Remplacez les lignes suivantes:

# Device locations
KEYBOARD_LOCATION   = "/dev/input/event0"
MOUSE_LOCATION      = "/dev/input/event1"

par celles-ci qui donnent les valeurs compatibles avec votre Ubuntu:

# Device locations
KEYBOARD_LOCATION   = "/dev/input/event1"
MOUSE_LOCATION      = "/dev/input/event5"

Le programme doit être lancé avec des droits root:

$ sudo ./key-status

Remarquez que la petite fenêtre de monitoring reste au dessus de toutes les autres et reste donc visible en permanence.

Sandisk Sansa e280

J’ai troqué mon iPod nano contre un Sandisk Sansa e280. Pourquoi? Parce que, quoi qu’on en dise, l’iPod est inutilisable sous Linux. Oui, Rhythmbox, Amarok ou Banshee sont soit-disant compatibles. Mais seulement pour certaines versions soft. Si vous faites un upgrade soft de votre iPod, c’est terminé, il devient inutilisable avec Linux.
Le Sandisk Sansa e280 n’est pas non plus totalement compatible avec Linux puisqu’il utilise le protocole MTP (Media Transfert Protocol) de Microsoft par défaut. Mais…vous pouvez le forcer en mode MSC (Mass storage device Class) qui le rend visible par linux comme un périphérique de masse au même titre qu’une clé USB. Il vous suffit dès lors de copier dans le Sansa e280 les fichiers audios que vous désirez.
L’inconvénient de forcer votre Sandisk Sansa en mode MSC est que le autres possibilités offertes par le mode MTP vous sont inaccessibles mais nous verrons qu’il est possible de mettre des photos (et même des vidéos mais je n’ai pas fait le test).
Pour être tout à fait complet, il existe un programme qui permet de tirer profit du mode MTP. Il s’agit de Gnomad2 qui se trouve dans les dépots Ubuntu. On en reparlera peut-être dans un prochain article.

La première chose a faire, lorsque vous recevez votre Sandisk Sansa est donc de le mettre en mode MSC. Pour cela, rendez-vous dans le menu Réglages (Settings), Mode USB et choisissez Auto detect ou MSC. Si ce menu n’apparaît pas, pas de panique, cela signifie juste que le firmware de votre Sandisk Sansa n’est pas à jour. Ouvrez votre navigateur Internet à l’adresse suivante http://www.sandisk.com/Retail/Default.aspx?CatID=1376 et téléchargez le fichier SansaUpdaterInstall.exe. Et oui, c’est un programme Windows. Il vous permettra de faire l’upgrade de votre lecteur. Une fois l’upgrade terminé, l’option Mode USB devrait apparaître dans le menu.
Fichiers présents sur le Sansa
Le Sandisk Sansa étant maintenant reconnu comme une clé USB, une icône devrait apparaître sur votre bureau dès que vous raccordez le lecteur à votre PC. Sur ma machine, le lecteur est nommé par Ubuntu Media 8,2 Gio. Vous pouvez voir sur la capture d’écran ci-contre les différents répertoires et fichiers présents sur le Sansa. S’y trouvent aussi les répertoires qui concernent les photos qu’on peut mettre sur le lecteur et dont on va reparler. Pour mettre des fichiers audios sur le Sansa, il suffit de les copier dans le répertoire MUSIC du lecteur.

Comme l’iPod, le Sandisk Sansa se base sur les Tags des fichiers audios pour faire son classement par artistes, par albums etc… Veillez donc à ce que ces tags soient à jour dans vos fichiers. Utilisez un programme comme EasyTag par exemple.

En ce qui concerne les photos ou fichiers graphiques, si vous copiez dans le dossier PHOTO des fichiers .jpg provenant de votre appareil photo, vous aurez un beau message disant que vous devez utiliser le programme Sansa Media Converter pour copier vos photos sur le lecteur. Ce programme n’est évidemment pas disponible pour Linux.
En fait, on peut contourner le problème en faisant soi-même le travail du programme de Sandisk. Comme vous pouvez le voir sur la copie d’écran ci-dessus, les photos sont stockées dans un répertoire Album. Vous pouvez créer autant d’albums que vous voulez et les appeler comme vous voulez. Dans ce répertoire Album, vous copiez vos photos après les avoir redimensionnées en 176 x 220 (la taille de l’écran) et converties en bmp 24 bits (R8G8B8) avec The Gimp par exemple.
Dans ce même répertoire PHOTO, il y a un répertoire appelé thumbnail qui contient les miniatures de vos photos. Dans ce répertoire qui doit impérativement porter ce nom-là, créez un autre répertoire avec le même nom que votre album. Dans ce répertoire, mettez-y les miniatures de vos photos au format bmp 24 bits (R8G8B8) 50 x 42 pixels.

Pour conclure, l’iPod par rapport au Sandisk Sansa est plus complet et possède plus de possibilités. Par contre l’iPod est inutilisable sous Linux (oui, je sais…). Le Sansa, par contre, a pour moi le gros avantage d’être utilisable sous Linux. De plus, il possède une capacité mémoire équivalente à l’iPod nano. Il reste un appareil propriètaire néanmoins.
En ce qui concerne la facilité d’utilisation, l’iPod est supérieur, il faut bien le reconnaitre mais par contre, je trouve la qualité sonore du Sandisk Sansa meilleure que celle de l’iPod. Surtout dans l’aigu qui est plus présent et plus précis que dans l’iPod.
Autrement dit, c’est un achat qui se justifie pleinement à mon sens et en plus, le Sandisk Sansa e280 est moins cher qu’un iPod nano 8Gb.
Pour ceux qui veulent du logiciel libre open source, vous pouvez toujours installer Rockbox sur ce lecteur. Il en existe une version qui s’installe en dual-boot avec le firmware d’origine.

sudo: unable to resolve host

Cet après-midi, voulant faire un backup d’un PC qui semble avoir une faiblesse du côté du disque dur, je lance le liveCD d’Ubuntu Hardy. Une fois Ubuntu démarré, je veux configurer le réseau pour faire ma sauvegarde et je modifie l’adresse IP, le nom d’hôte (hostname) de la machine de façon à ce qu’elle soit reconnue par le DNS. Et là, surprise, ça ne fonctionne pas du tout. Réseau non-accessible. Je vérifie tous les paramètres du réseau et notamment le fichier /etc/hosts et je m’aperçois qu’il contient ceci:

127.0.0.1    localhost
127.0.1.1    ubuntu 

Autrement dit, mon changement de hostname via le le gestionnaire de réseau (Network manager – menu Système/Administration/Réseau) n’a pas été pris en compte au niveau du fichier /etc/hosts.
Pas de problème, me dis-je, il suffit de modifier ce fichier à la main en tapant dans un terminal:

$ sudo gedit /etc/hosts
sudo: unable to resolve host nouveau_hostname

nouveau_hostname est le nouveau nom d’hôte que je voulais donner à la machine. Mais la surprise est qu’il n’y a plus moyen du tout d’utiliser sudo. il semblerait que sudo fasse référence d’une façon ou d’une autre à ce hostname. Tout utilisation ou plutôt tentative d’utilisation de sudo échoue avec ce message d’erreur.
Heureusement que via l’onglet hôtes du gestionnaire de réseau, je suis parvenu à modifier le fichier /etc/hosts sinon, j’en serais encore au même point avec un sudo inutilisable.
En bref, si, lorsque vous utilisez sudo vous recevez comme message d’erreur:

sudo: unable to resolve host hostname

pensez à vérifier votre fichier /etc/hosts. il est plus que probable que celui-ci soit incorrect.

C++ – Comment capturer une exception

Il y a trois façons de capturer une exception: par valeur, par référence ou par pointeur.

Capture par valeur

Capturer une exception par valeur a deux inconvénients principaux. D’abord cela nécessite une copie de l’objet ce qui, si cet objet est de taille importante, n’est pas très efficient. Ensuite, copier un objet demande du temps et donc une capture par valeur sera forcément plus lente. De plus, si les ressources disponibles sont déjà faibles, cette copie pourrait elle-même provoquer une exception. Générer une exception quand une autre exception est active provoque l’appel de la fonction terminate(). Ce qui n’est pas à conseiller.

Capture par référence

C’est la méthode à préférer. C’est une méthode plus efficiente que par valeur et en plus, les références conservent l’aspect polymorphique des objets. Mais faut-il capturer par référence constante ou non. La règle habituelle s’applique ici aussi. Si on prévoit de ne rien changer à l’objet, autant indiquer qu’il est constant. le compilateur donnera une erreur chaque fois qu’on essaiera de modifier l’objet et tout programmeur saura directement en voyant la référence constante que l’objet ne sera pas modifié.

Capture par pointeur

On pourrait très bien capturer par pointeur mais le problème ici est qui est responsable de la libération de la mémoire et surtout comment ?
Considérons le code suivant:

void f1()
{
  int a = 10;
  throw &a;
}

void f2()
{
  throw new int(10);
}

void f3()
{
  throw new int[10];
}

int main()
{
  try
  {
    f1();
    // ou
    f2();
    // ou
    f3();
  }
  catch( int * p )
  {
    //comment libérer la mémoire?
  }
} 

Le problème ici est clairement que dans le catch(), on ne sait pas s’il faut libérer la mémoire avec delete, delete[] ou ne pas la libérer du tout. c’est impossible à savoir. Autrement dit, on ne capture pas d’exception par pointeur.