Introduction au C++
Dans cette première partie, nous allons voir une introduction rapide au langage C++ lui même, indépendamment de la partie graphique qui sera introduite dans la partie suivante. Ces notions de langage sont donc très génériques, mais il est important de les comprendre pour pouvoir les utiliser dans les programmes plus complexes de la suite.Premier programme
> Téléchargez l'archive suivante et décompressez la: 01_hello_world.zip- - Le fichier de code C++ est main.cpp.
- - Le fichier CMakeLists.txt permet d'aider à la compilation du code par le biais de l'outils CMake, notamment pour les utilisateurs sous Windows.
Le fichier main.cpp contient le code suivant:
- notez que vous pouvez également créer simplement un fichier main.cpp et écrire le code directement.
#include <iostream> int main() { std::cout << "Hello world" << std::endl; return 0; }
- 1. Compilez le code (c-a-d convertir le code en un fichier binaire exécutable par le système)
- 2. Lancez l’exécutable correspondant.
Ces deux étapes dépendent de votre système. Pour cela, vous pouvez vous référer à la démarche indiqué préalablement pour la mise en place de votre système.
Si vous êtes sous Windows
- La procédure la plus simple est d'utiliseur CMake sur le fichier CMakeLists.txt afin de créer un fichier de configuration pour Visual Studio. Visual Studio peut alors être être utilisé pour compiler et exécuter le programme.
Si vous êtes sous Linux ou MacOS
- Vous avez plusieurs solutions dans ce cas de figure pour un programme aussi simple (mono-fichier sans aucune dépendance).
-
- Soit suivre la démarche de compilation expliquée dans le tutorial de mise en place de votre système. C'est à dire
-
- a) soit à l'aide de QtCreator à partir du fichier CMakeLists.txt
- b) soit en ligne de commande par le biais l'appel à cmake
- c) Soit compiler directement en ligne de commande en appelant le compilateur g++ (ou, au choix, clang++) sur le fichier main.cpp
- Rappels de quelques commandes du terminal
# Lister les fichiers du repertoire courant ls # Se déplacer dans le répertoire "directory" cd directory # Se déplacer dans le répertoire parent cd .. # Lancer un fichier exécutable (ex. pgm) dans le répertoire courant ./pgm # Lancer un fichier exécutable (pgm) contenu dans le répertoire directory depuis le répertoire parent directory/pgm
- N'oubliez pas non plus que vous pouvez utiliser la touche "tabulation" pour compléter automatiquement les noms de fichiers ou commande que vous avez commencé à taper dans le terminal.
Analyse du code
Si tout se passe correctement, et ce indépendamment de votre système, l'exécution du programme doit aboutir à l'affichage du message "Hello world" en ligne de commande.Voici l'explication de chaque ligne de ce code:
- #include <iostream>
-
- - #include permet d'inclure le code d'un autre fichier. Il permet le mécanisme d'inclusion de bibliothèque externe en C++.
- - #include <FileName> permet l'inclusion du fichier nommé `FileName`. Les chevrons indiquent que ce fichier doit être préférentiellement cherché dans les fichiers système (ce qui est le cas pour iostream). Le mécanisme d'inclusion est très simple car le contenu du fichier est litéralement copié/collé.
- - iostream correspond à la bibliothèque standard C++ d'entrée sortie (iostream = Input Output Stream). Elle permet en particulier l'affichage sur la ligne de commande.
- int main()
-
- Correspond au point d'entrée, ou "de départ", de l'exécutable, c'est-à-dire la fonction qui va être appelée automatiquement lorsque vous lancez l'exécutable.
- Tout programme C++ doit nécessairement contenir une (et une seule) fonction appelée main.
- std::cout << "Hello World" << std::endl;
-
- std :: cout << syntaxe standard pour afficher du texte sur la ligne de commande (ici "Hello World")
-
- - cout signifie Common Output. (réfère par défaut à la ligne de commande sauf si l'on a redirigé la sortie standard)
- - std::cout est le nom complet de l'objet `cout` qui est présent dans l'espace de nommage (namespace) std (standard library).
- - :: est appelé l'opérateur de résolution de portée (scope resolution operator). Ici il permet de trouver l'objet cout dans l'espace de nom std
- - << est un opérateur C++ (c-a-d un symbole utilisé en tant que fonction). Ici l'opérateur << est utilisé pour envoyer la chaine de caractère (string) à l'objet std::cout afin de l'afficher en ligne de commande.
- <<std::endl Ajout un saut de ligne à la fin de l'affichage. endl réfère à end of line.
- return 0; Valeur de retour de l'exécutable (renvoi au processus appelant - par exemple la ligne de commande). Par convention une valeur de retour de 0 indique que le programme s'est terminé sans erreurs.
Remarques générales:
- - Chaque instruction de code C++ doit nécessairement terminer par un point virgule `+;+`
- - Contrairement à Python, mais similairement à Java, l'idendation et les sauts de lignes n'ont pas d'importance sur le code.
C++ moderne
Le langage C++ possède une longue histoire depuis sa création initiale en 1985. Le langage fut initialement conçu comme une extension du langage C avec l'introduction de l'orienté objet. Il reste encore aujourd'hui compatible avec le langage C, mais peut être utilisé suivant de multiples approches.- - En 1998, le langage C++ est normalisé (ISO/IEC) dans sa version C++98
- - Une version avec de nombreux ajouts majeurs est apportée en 2011 dans la version C++11, appelée également C++ moderne. Différents ajouts se sont poursuivis et l'on peut noter les versions C++14, C++17, C++20. La prochaine à venir étant C++23.
La bonne utilisation de la syntaxe C++ moderne permet d'aboutir à des codes plus simples et lisibles, tout en gardant une efficacité optimale d'exécution. Dans ces TD, nous utiliserons une syntaxe compatible avec la norme C++14.
Modifiez votre fichier main.cpp de manière à ce qu'il contienne le code suivant:
- rem. Si vous compilez en ligne de commande, vous pouvez également rapidement créer un nouveau fichier ayant un autre nom, et adapter la compilation à celui-ci. Si vous utiliser un IDE, il sera plus rapide de simplement modifier votre fichier existant.
#include <iostream> #include <string> #include <vector> int main() { std::string str = "Hello "; auto str2 = str + "World"; std::cout << str2 << std::endl; std::vector<int> vec = {4,1,3,5}; vec[0] -= 2; vec.push_back(10); for(auto x : vec) std::cout << x << " "; std::cout<<std::endl; return 0; }
La compilation et l'exécution de ce programme se réalisent à l'aide des lignes de commande suivante:
Remarques sur la compilation (Linux et MacOS uniquement)
Ces notions ne sont utiles que pour les étudiants qui compilent sous Linux ou MacOS directement en ligne de commande- - Si vous compilez avec l'appel direct à g++, il peut être nécessaire d'indiquer l'option -std=c++14 (ou toute version ultérieur). Cela permet d'indique explicitement au compilateur que le code doit être analysé suivant la norme 2014. Dans le cas où votre système possède une version de GCC récente, cette ligne n'est pas indispensable.
-
- rem. g++ correspond à l'appel du compilateur GCC pour compiler du code c++.
- - D'une manière générale, on activera les options de debug, de warning, et on forcera le nom de l'exécutable lors de la compilation. On préférera ainsi un appel à la compilation sous la forme
g++ -g -Wall -Wextra -O2 -std=c++14 [fichier].cpp -o pgm ./pgm
- -g: Active les indications de debugs du fichier exécutable
- -Wall -Wextra: Active les warnings lors de la compilation
- -O2: Active les optimisations du compilateur
- -o pgm: Génére un fichier de sortie (ici l'exécutable) dont le nom est paramétré (ici pgm)
Remarques sur le code
- std::string correspond à la classe standard C++ permettant de manipuler des chaines de caractères.
- Le type auto (uniquement depuis C++11) permet de ne pas avoir à écrire explicitement le type (ici std::string) lorsque celui-ci peut
être automatiquement déterminé au moment de la compilation.
- std::vector<int> correpond à un object de la bibliothèque standard C++ stockant des entiers de manière contiguë en
mémoire.
- La syntaxe for(auto x : vec) { ... } permet de parcourir de manière générique l'ensemble des éléments d'un conteneur (ici un
vector) de la bibliothèque standard.
Remarques générales sur le C++
Pourquoi apprendre C++
C++ est actuellement le langage de programmation dominant pour les logiciels scientifiques interactifs de large envergure. Que ce soit pour des applications en 3D et en graphique: Maya, 3DStudio, ZBrush, Houdini, Photoshop, Unreal Engine, etc., mais également dans de nombreux autres domaines: MS Word, Facebook, Tensor Flow, etc. possèdent tout un coeur (partie du programme réalisant les taches les plus critiques de calculs) codé en C++.
Notez que la plupart de ces logiciels possèdent des interfaces avec des langages de scripts de plus haut niveau afin de pouvoir être utilisés plus efficacement pour réaliser de petits prototypes (ex. Python, Lua, C#, etc.). Cependant ces scripts font appel aux fonctionnalités au coeur du logiciel qui sont codées pour leur part en C++. Ne négligez donc pas l'apprentissage du C++ si vous souhaitez être en mesure de pouvoir comprendre le fonctionnement de ces logiciels de manière approfondie.
Principes du C++
Principe généraux et comparaisons à d'autres langages
Le langage C++ est dit multi-paradigm. C’est-à-dire qu’il peut être utilisé dans une vaste gamme d’application, et suivant plusieurs approches (procédural, objet, fonctionnel, meta-programmation, etc.). C'est à l'heure actuelle l'un des seuls langages ayant un écosystème stable et complet permettant, d'un côté, de développer à très bas niveau en étant très proche du système d'exploitation/matériel (et donc très efficace), et d'un autre côté de proposer des abstractions de plus haut niveau quasiment sans aucun surcout en temps de calcul.
A titre de comparaison:- - Java est largement utilisé dans le développement de logiciels de services de grande envergure. Mais son execution par le biais d'une machine
virtuelle le rend moins adapté à une utilisation pour des applications temps-réels, et/ou associé à du calcul scientifique, et impose l'utilisation du
développement objet.
- - Python est le langage de haut niveau qui se développe largement pour le prototypage de calcul scientifique (numpy, scipy, pytorch, binding pour
TensorFlow, etc.). Son absence de typage statique et son temps de calcul le rendent cependant moins adapté pour passer à l'échelle d'un logiciel de
grande envergure, surtout si celui-ci doit s'exécuter en temps réel et/ou interagir avec l'utilisateur.
- - D'autres langages récents encore en cours de développement (Rust, Julia, nim, etc.) possèdent pour certains les avantages de C++ sans en avoir les inconvénients, mais manquent encore de maturité (stabilité des instructions en fonction des versions, bugs du compilateur, etc) et d'environnements de développement avancé permettant une utilisation dans le cadre industriel.
Le pendant de la richesse du langage C++ est cependant sa complexité. Il n’existe ainsi pas une unique manière de coder en C++ (utilisation de pointeurs à la C, pur objet, fonctionnel, etc); chaque approche pouvant se prêter plus ou moins à un type d’application ou d’habitude. Le C++ est un langage très technique difficile à lire et à écrire de par la précision et la rigueur nécessaire à l'écriture du code associé (type de variable, positionnement en mémoire, template, etc.).
Dans le cas présent, nous utiliserons principalement une programmation procédurale, où les objets seront généralement de petites structures allouées
statiquement afin de pouvoir être créées et manipulées de manière légère (en mémoire) et rapide (en temps de calcul). Nous utiliserons les surcharges
d'opérateurs pour modéliser et manipuler aisément des objets mathématiques (vecteurs, matrices). Nous utiliserons également largement les conteneurs de la
librairie standard permettant de gérer des objets dynamiques sans avoir à manipuler explicitement les allocations mémoires.
A l'opposé, nous n'aborderons dans ce cours pas (ou que très marginalement) la gestion manuelle de la mémoire, l'utilisation de pointeurs, le
polymorphisme, les templates.
Notion de langage compilé
C++ est un langage dit "compilé". C'est-à-dire que le code C++ est converti en code assembleur qui peut être directement exécuté par le processeur central (CPU). La compilation peut être une opération longue. Par contre, une fois celui-ci compilé, l'exécution est généralement beaucoup plus rapide que l'exécution d'un langage interprété.
C++ est un langage dit "typé statiquement" (à l'opposé des langages de scripts dits "dynamiques"). Toute variable doit avoir un type fixe connu au
moment de la compilation, et ce type ne peut pas varier au cours de la durée de vie de la variable.
Le typage des variables implique d'être rigoureux lors de l'écriture du code. Cette plus grande rigueur permet cependant au compilateur d'être plus précis
pour détecter les erreurs (avant même l'exécution du programme) et vérifier la cohérence du code (ex. passage de données ayant un type cohérent d'une
fonction à l'autre, etc.). Le typage statique est souvent indispensable pour le développement de logiciels de grande envergure (100aines-milliers -
millions de lignes de codes).
Références
Pour approfondir vos connaissances en C++, il vous est possible de vous référer au cours INF442 qui aborde davantage de détails sur le langage, ainsi qu'au livre "The C++ Programming Language" de Bjarne Stroustrup (créateur du langage C++).
De manière générale, n'hésitez pas à rechercher des informations sur la référence en ligne du langage ainsi que de sa bibliothèque standard : CPP Reference.