====== C++ ======
[[:san.cplusplus:visualstudio|Astuces Visual Studio]]
Probleme du const int global pour declarer un tableau:
http://bytes.com/topic/c/answers/222781-specifying-global-array-size-const-int
It does distinguish between a literal and a const int in either
context. The difference is that variable length arrays (VLAs) are
legal in a local context. In the following:
int main(void)
{
#define TEN 10
const int ten = 10;
int arr0[TEN];
int arr1[ten];
...
}
arr0 is an ordinary array, but arr1 is a VLA.
Excellent cours (avec lib standard):\\
http://casteyde.christian.free.fr/cpp/cours/online/c207.html
http://www.cplusplus.com/doc/tutorial/
Bonne Faq:\\
http://cpp.developpez.com/faq/cpp/
===== analyse statique - static analysis =====
If by Open Source, you really meant "free", then Microsoft's prefast analysis is a good one. Windows-only ofcourse. It is fully integrated in Visual Studio & the compiler. e.g.:\\
cl /analyze Sample.cpp\\
Concerning the GNU compiler, gcc has already a builtin option that enables additional warning to those of -Wall. The option is -Weffc++ and it's about the violations of some guidelines of Scott Meyers published in his books "Effective and More Effective C++".\\
CppCheck is open source and cross-platform.\\
https://wiki.mozilla.org/Static_Analysis\\
http://en.wikipedia.org/wiki/List_of_tools_for_static_code_analysis#C.2FC.2B.2B\\
===== diagram uml reverse engineering C++ =====
dia et cpp2dia
http://stackoverflow.com/questions/8015471/uml-free-reverse-engineering-tool-for-c-h-cpp-class-diagram
http://staruml.io/download
===== C++ tips =====
If you use [] when you call new, you must use [] when you call delete.
If you don ' t use [] when you call new, don ' t use [] when you call delete.
Prefer C++-style comments
Prefer new and delete to malloc and free.
The problem with malloc and free (and their variants) is simple:
they don't know about constructors an destructors.
Prefer to
"prefer the compiler to the preprocessor
const double ASPECT_RATIO = 1.653;
class GamePlayer {
private:
static const int NUM_TURNS = 5; // constant declaration
int scores[NUM_TURNS]; // use of constant
...
};
const int GamePlayer::NUM_TURNS; // m
Use delete on pointer members in dest ructors.
Until 1993, C++ required that operator new return 0 when it was unable to satisfy a memory request. The current behavior is for operator new to throw a std::bad_allocexception
The easiest way to do that is to take advantage of set_new_handler, because it works with both forms
La norme ISO C99 impose de définir des types portables afin de régler ces problèmes sur toutes les architectures existantes. Ces types sont définis dans le fichier d'en-tête stdint.h. Il s'agit des types int8_t, int16_t, int32_t et int64_t, et de leurs versions non signées uint8_t, uint16_t, uint32_t et uint64_t.
Instance/classes
constructeur/destructeur(virtual)/constructeur de copie
class MaClasse
{
public:
MaClasse( const MaClasse & ); // ceci est le constructeur de copie
};
pointeurs/references/passage par valeur\\
lifting = rafinement de templates\\
partie publique = interface\\
encapsulation=\\
J'applique une méthode simple : la question à se poser est la suivante : est-ce que X est un genre de Y, ou est-ce que X utilise un Y ?\\
Si la réponse est X est un genre de Y, il s'agit d'un cas où je dérive une classe.\\
Si la réponse est X utilise Y, il s'agit d'un cas où je vais encapsuler une classe.\\
\\
Le polymorphisme, c'est la capacité d'une expression à être valide quand les valeurs présentes ont des types différents. On trouve différents types de polymorphismes :\\
class Person
{
public:
// accesseur : renvoie le nom
const std::string & GetName() const // notez le const
{
return this->name;
}
// mutateur : change le nom
void SetName( const std::string & NewName )
{
this->name = NewName;
}
private:
std::string name; // nom de la personne
};
Qu'est-ce que la coercition ?\\
Derrière cette expression se cache tout simplement les mécanismes de conversion implicite \\
double result = op1 + op2; // polymorphisme de coercition
\\
Qu'est-ce que la surcharge ?\\
Il s'agit probablement d'une des premières caractéristiques du C++ présentées : la capacité à surcharger une opération avec différentes signatures\\
\\
Qu'est-ce que le polymorphisme paramétrique ?\\
Le polymorphisme paramétrique passe par l'utilisation des techniques génériques pour offrir un même service pour tout un ensemble de types\\
template
void dump(T var)
{
std::cout<
Qu'est-ce que le polymorphisme d'inclusion ?\\
Souvent résumé tout simplement (et trop hativement) à 'polymorphisme', le polymorphisme d'inclusion s'appuie sur l'héritage public\\
fonctions virtuelles\\
void function(IInterface const &var_)
{
var_.Action();
}
class IInterface
{//...
};
class CConcrete : public IInterface
{//...
};
int main()
{
CConcrete c;
Fonction(c);
return 0;
}
class Widget
{
public:
virtual ~Widget() { /* ... */ }
void show()
{
// ...
do_show();
// ...
}
// ...
private :
virtual void do_show()=0; // fonction virtuelle pure
};
class Button : public Widget
{
private :
virtual void do_show() { std::cout << "Button" << std::endl; }
// ...
};
class Textfield : public Widget
{
private :
virtual void do_show() { std::cout << "Textfield" << std::endl; }
// ...
};
void show_widget(Widget& w)
{
w.show();
}
/* ... */
Button b;
Textfield t;
show_widget(b); // affiche "Button"
show_widget(t); // affiche "Textfield"
Quels sont les enjeux associés aux techniques Orientées Objets ?\\
Les techniques OO sont la meilleure façon connue de développer de grosses applications ou des systèmes complexes.\\
\\
L'industrie du logiciel n'arrive pas à satisfaire les demandes pour des systèmes logiciels aussi imposants que complexes, mais cet échec est dû à nos succès : nos réussites ont habitué les utilisateurs à toujours en demander plus. Malheureusement, nous avons ainsi créé une demande du marché que les techniques 'classiques' de programmation ne pouvaient satisfaire. Cela nous a obligé à créer un meilleur paradigme.\\
\\
le C++ permet de programmer OO, mais il peut aussi être utilisé comme un langage classique ("un C amélioré"). Si vous comptez l'utiliser de cette façon, n'espérez pas profiter des bénéfices apportés par la programmation OO.\\
Fred* p = new Fred();
Le destructeur Fred::~Fred() va être appelé automatiquement quand vous utiliserez delete
Sélectionnez
Que signifie 'friend' ?
Quelque chose qui permet à une classe d'offrir des droits d'accès privilégiés à une autre classe ou fonction.
const signale que la variable ne peut pas changer de valeur, et que le compilateur refusera qu'on le fasse.
static (dans le cas de la classe) signifie que la variable n'existe qu'en un seul exemplaire, elle est globale à la classe en quelque sorte. Autrement, chaque objet du type de la classe dispose de sa propre copie.
Une telle syntaxe (déclaration et définition en un seul coup) est possible en C++, mais seulement parce qu'elle vérifie certaines conditions : il s'agit d'une variable constante, statique, et de type entier. En d'autres termes ces déclarations ne compileraient pas :
Sélectionnez
class MaClasse
{
static int x = 0; // erreur : pas constant
const int y = 5; // erreur : pas statique
static const float z = 4.2f; // erreur : pas entier
};
delete p; // p->~Fred() est appelé automatiquement
Qu'est-ce que le "fiasco dans l'ordre d'initialisation des variables statiques" ?
Un moyen subtil de planter votre programme.
Le fiasco dans l'ordre d'initialisation des variables statiques est un des aspects les plus subtils et habituellement mal compris du C++. Malheureusement, il est très difficile à détecter étant donné que l'erreur se produit avant même le début de l'exécution du main().
Supposons que l'on ait deux objets statiques x et y qui se trouvent dans des fichiers sources séparés (x.cpp et y.cpp) Supposons ensuite que l'initialisation de l'objet y (typiquement le constructeur de l'objet y) appelle une fonction membre de l'objet x.
C'est aussi simple que cela.
La tragédie est que vous avez 50% de chances de vous planter. S'il arrive que l'unité de compilation correspondant à x.cpp soit initialisée avant celle correspondant à y.cpp, tout va bien. Mais si l'unité de compilation correspondant à y.cpp est initialisée d'abord, alors le constructeur de y sera en route avant le constructeur de x, et vous êtes cuit. C'est-à-dire que le constructeur de y appellera une fonction de l'objet x, alors que ce dernier n'est pas encore construit.
Si vous pensez que c'est "excitant" de jouer à la roulette russe avec la moitié du barillet chargé, vous pouvez vous arrêter de lire ici. Si au contraire vous aimez augmenter vos chances de survie en prévenant les désastres de manière systématique, vous serez probablement intéressé par la question suivante.
Note : le fiasco dans l'ordre d'initialisation des variables statiques peut aussi se produire, dans certains cas, avec les types de base.
#include "Fred.hpp"
Fred& x()
{
static Fred* ans = new Fred();
return *ans;
}
Que signifient public, private et protected ?
Un membre déclaré public dans une classe peut être accédé par toutes les autres classes et fonctions.
Un membre déclaré protected dans une classe ne peut être accédé que par les autres membres de cette même classe ainsi que par les membres des classes dérivées.
Un membre déclaré private dans une classe ne peut être accédé que par les autres membres de cette même classe.
Ces mots-clés permettent également de modifier la visibilité des membres dans la classe dérivée lors d'un héritage :
Héritage
Accès aux données public protected private
public public protected private
protected protected protected private
private interdit interdit interdit
Quand dois-je faire un héritage public ? protégé ? privé ?
public : uniquement si l'héritage porte une sémantique EST-UN ;
privé : lorsque l'héritage porte une sémantique EST-IMPLEMENTE-EN-TERMES-DE et ne supporte pas la sémantique EST-UN ;
protégé : si vous avez une bonne raison, la rédaction sera curieuse de la connaître.
Le LSP (pour Liskov substitution principle) est un principe général de programmation s'énonçant de la façon suivante :
Sélectionnez
Partout où un objet x de type T est attendu, on doit pouvoir passer un objet y type U, avec U héritant de T.
Pouvez-vous me donner une raison simple pour laquelle la virtualité est si importante ?
L'appel dynamique permet d'augmenter la réutilisabilité en autorisant le 'vieux' code à appeler du nouveau code.
Avant l'apparition de l'orientation objet, la réutilisation du code se faisait en appelant du vieux code à partir du nouveau code. Par exemple, un programmeur peut écrire du code appelant du code réutilisable comme printf(), ....
Avec l'orientation objet, la réutilisation peut aussi être accomplie via l'appel de nouveau code par de l'ancien. Par exemple, un programmeur peut écrire du code qui est appelé par un framework qui a été écrit par son arrière grand-père. Il n'y a pas besoin de modifier le code écrit par l'arrière grand-père. En fait, il n'a même pas besoin d'être recompilé. Et si jamais il ne restait que le fichier objet, et que le code écrit par l'arrière grand-père ait été perdu depuis 25 ans, cet ancien fichier objet appellera le code avec les nouvelles fonctionnalités sans rien changer d'autre.
C'est cela l'extensibilité, et c'est cela l'orientation objet.
Les fonctions virtuelles sont-elles un mécanisme important en C++ ?
OUI
Sans les fonctions virtuelles, le C++ ne serait pas un langage orienté objet.
Une fonction virtuelle signifie qu'elle peut être supplantée par une fonction d'une classe fille.
Une fonction virtuelle pure signifie qu'elle doit être supplantée par une fonction d'une classe fille.
===== STL - Standard Template Library =====
{{:san.cplusplus:diagramme_uml_de_stl.png?200|STL en UML}}\\
http://www.cplusplus.com/reference/stl/\\
http://www.commentcamarche.net/faq/11255-introduction-a-la-stl-en-c-standard-template-library\\
http://www.sgi.com/tech/stl/table_of_contents.html\\
#include
#include
int main() {
std::list ma_liste;
ma_liste.push_back(4);
ma_liste.push_back(5);
ma_liste.push_back(4);
ma_liste.push_back(1);
std::list::const_iterator
lit (ma_liste.begin()),
lend(ma_liste.end());
for(;lit!=lend;++lit) std::cout << *lit << ' ';
std::cout << std::endl;
return 0;
}
#include
#include
int main() {
std::vector mon_vecteur;
mon_vecteur.push_back(4);
mon_vecteur.push_back(2);
mon_vecteur.push_back(5);
// Pour parcourir un vector (même const) on peut utiliser les iterators ou les index
for(std::size_t i=0;i mon_vecteur(5,69); // crée le vecteur 69,69,69,69,69
v[0] = 5;
v[1] = 3;
v[2] = 7;
v[3] = 4;
v[4] = 8;
return 0;
}
#include
===== Principaux Design Patterns=====
[[http://come-david.developpez.com/tutoriels/dps/]]