77
Développement natif en C++ Christophe Pichaud – Architecte Sogeti Loïc Joly – Architecte CAST Code / Développement

Développer en natif avec C++11

Embed Size (px)

DESCRIPTION

Articulé autour de C++ 11, cette session amène celui qui y assiste aux fondamentaux du développement logiciel : libraries, dépendances, TR1 et C++0X les fondations de C++ 11, runtime C alias CRT, runtime C++ alias STL, agilité en C++, ALM en C++, Windows 8 et C++, C++ et Windows 8 avec le nouveau modèle COM nommé WRL.

Citation preview

Page 1: Développer en natif avec C++11

Développement natif en C++

Christophe Pichaud – ArchitecteSogeti

Loïc Joly – ArchitecteCAST

Code / Développement

Page 2: Développer en natif avec C++11

Design/Général

Mobilité/Consumer/B2C

Code/ Dev Office / B2B / LOB / entreprise

Architecture / Azure / Cloud

Serveurs / Entreprise / Réseaux / IT

Phone / Mobilité

Gaming / Divertissement

Page 3: Développer en natif avec C++11

C++11 LES GRANDS THÈMESChapitre 1

Développement natif en C++ 11

Page 4: Développer en natif avec C++11

C++11 est comme un nouveau langage Evolutions du langage – standard C++ 11

Changer le codage avec des styles/guidances/idioms. C’est ce qui définit le nouveau langage

Pourquoi une session C++ ?

Page 5: Développer en natif avec C++11

Pourquoi le C++ ?Optimiser Exemple C++ ?

Le temps/coût de développement

Interface d’accès BdD Non

Le temps d’exécution Jeux, temps réel Oui

Le coût hardware Ferme de serveurs Oui

L’énergie nécessaire Informatique mobileCentre de calcul

Oui

• Dans de nombreux domaines, le coût de développement est devenu très faible face au coût d’exploitation

Page 6: Développer en natif avec C++11

Pourquoi choisir C++ ?

“The going word at Facebook is that ‘reasonably written C++ code just runs fast,’ which underscores the enormous effort spent at optimizing PHP and Java code. Paradoxically, C++ code is more difficult to write than in other languages, but efficient code is a lot easier.” – Andrei Alexandrescu

Page 7: Développer en natif avec C++11

The C++ Standards Commitee http://www.open-std.org/jtc1/sc22/wg21/

2011 : Approbation du standard C++0x Amélioration de l’implémentation dans « VC++ 11 »

2008: Draft pour C++0x Implémentation (partielle) dans Visual C++ 2010

2005: TR1= Library Technical Report 1 Visual C++ 2008 + TR 1

2003: TC1 = corrections C++98 1998: C++ devient un standard ISO (« C++98 »)

La roadmap C++

Page 8: Développer en natif avec C++11

TR1.. C++0x.. C++ 11

TR1 - Technical Report 1shared_ptr<T>

weak_ptr<T>

unique_ptr<T>

regex

tuple

array

C++ 0xlambdas

r-value reference

auto

decltype

static_assert

Thread

mutex

future<T>

vector<vector<int>>

variadic templates

Page 9: Développer en natif avec C++11

C++, mythes et réalités

Template meta-programming

Des macros et de goto !

C’est du C !

Un langage orienté objet compliqué !

Bas niveau !

Non sécurisée, dangereux !

Code dur à maintenir

Code crado mais je continue sur le même modèle…

Compliqué à apprendre !

Peu productif !

cast

new / delete

pointeurs

Orienté objet

Un bon code

principes et techniques

Interfaces richesStructure de données

compactes et efficaces

le style C++ 11

gestion des erreurs

Page 10: Développer en natif avec C++11

Le C++11 permet de faire du code Clean, Safe, Fast.Clean & Safe : le nouveau style moderneFast : l’a toujours été

Evolution du style C++

Page 11: Développer en natif avec C++11

Aperçu des différences

Then Nowcircle* p = new circle( 42 );

vector<shape*> vw;load_shapes( vw );

for( vector<circle*>::iterator i = vw.begin(); i != vw.end(); ++i ) { if( (*i)->weight() > 100 ) cout << **i << “ is a match\n”;}

for( vector<circle*>::iterator i = vw.begin(); i != vw.end(); ++i ) { delete *i;}

delete p;

auto p = make_shared<circle>( 42 );

auto vw = load_shapes();

for( auto& s : vw ) { if( s->weight() > 100 ) cout << *s << “ is a match\n”;}

T* shared_ptr<T>

new make_shared

Pas de delete. Gestion automatique du cycle de

vie. exception-safe

range-for

auto type deduction

not exception-safe

missing try/catch, __try/__finally

return by value + move

+ auto again to deduce

vector<shared_ptr<shape>>

Page 12: Développer en natif avec C++11

Plus grosse « difficulté du C++ » : la gestion de mémoireIl n’y a pas de manière unique d’allouer la mémoire en C++Heureusement : RAII= Resource Acquisition Is Initialization

Destruction déterministe (i.e. pas besoin de « using ») Applicable à toutes les ressources « précieuses :

Mémoire fichiers, sockets, handles Windows

Gestion de la mémoire

“C++ is the best language for garbage collection principally because it creates less garbage.”

Bjarne Stroustrup

Page 13: Développer en natif avec C++11

Effective C++, Third Edition (2005) by Scott Meyers: "shared_ptr may be the most widely useful

component in TR1."

C++ Coding Standards (2005) by Herb Sutter and Andrei Alexandrescu: "Store only values and smart pointers in containers.

To this we add: If you use [Boost] and [C++TR104] for nothing else, use them for shared_ptr."

Paroles d’experts !

Page 14: Développer en natif avec C++11

Un template C++ disponible dans <memory>Basé sur le comptage de référencesGain de productivité & robustesse importants avec impact minimal sur les perfsCompatible avec les conteneurs STLCompatible avec le polymorphisme :

shared_ptr<Derived> est convertible en shared_ptr<Base> Ne casse pas le mécanisme de comptage des références Besoin de convertir (cast) ?

static_pointer_cast<Derived>(spBase) dynamic_pointer_cast<Derived>(spBase)

Caractéristiques de shared_ptr<T>

Page 15: Développer en natif avec C++11

Possibilité d’instancier shared_ptr<T> sans modifier TLa gestion des références (uses/weaks) est dans le shared_ptrFonctionne avec les types prédéfinis: shared_ptr<int>S’incorpore dans le code sans modifier les types existantsUn même type peut être manipulé parfois via un shared_ptr et d’autres fois via d’autres mécanismes

shared_ptr est Non-Intrusif

Page 16: Développer en natif avec C++11

VS 2008 SP1 (VC9 SP1): shared_ptr<T> sp(new T(args)); shared_ptr<T> sp(new T(args), del, alloc);

VS 2010 (VC10): auto sp = make_shared<T>(args); auto sp = allocate_shared<T>(alloc, args);

Simple et élegant Écrire le type T une seule fois

Robuste Pas de fuite avec shared_ptr

Efficace Allocation de mémoire dynamique standard

make_shared<T>()

Page 17: Développer en natif avec C++11

Une seule référence de l’objetunique_ptr<Cat> c(new Cat);unique_ptr<Cat> c2(Cat::Load(…));

Remplace auto_ptr, qui est obsolèteCompatible avec les collections STL (containers) Non copiable mais déplaçable

unique_ptr<Cat> c(new Cat); unique_ptr<Dog> d; d.reset(new Dog); unique_ptr<Monster> m_src(new Monster); unique_ptr<Monster> m_dest(move(m_src));

unique_ptr<T>

Page 18: Développer en natif avec C++11

DELETE

Page 19: Développer en natif avec C++11

C++ 11 : Best-Of

Page 20: Développer en natif avec C++11

vector<string> v;v.push_back( “Geddy Lee” );

array<string,50> a;

Containers STLmap<string, string> phone;

phone[“Alex Lifeson”] = “+1 (416) 555-1212”;

multimap<string, string> phone;

phone[“Neil Peart”] = “+1 (416) 555-1212”;

phone[“Neil Peart”] = “+1 (905) 555-1234”;

unordered_map<string, string> phone;

phone[“Alex Lifeson”] = “+1 (416) 555-1212”;

unordered_multimap<string, string> phone;

phone[“Neil Peart”] = “+1 (416) 555-1212”;

phone[“Neil Peart”] = “+1 (905) 555-1234”;

container par défaut: vector

compact, efficace, cache, préfetch

dictionary: map (arbre) ou

unordered_map (hash)

vecteur de taillle fixe: array

compact, efficace, cache, préfetch

Page 21: Développer en natif avec C++11

Itération au travers un “range”

void f(vector<double>& v) {

for (auto x : v) cout << x << '\n';

for (auto& x : v) ++x; // using a reference to allow us to change the value

}

Boucle for avec range

Page 22: Développer en natif avec C++11

nullptr exprime un pointeur nulCe n’est pas un int

class Foo {public: Foo(const char *s); Foo(int n);}…Foo f(NULL);Foo f(nullptr);

nullptr

Page 23: Développer en natif avec C++11

NULL

Page 24: Développer en natif avec C++11

La problème d’espace est résolu

list<vector<string>> lvs;

Syntax Error de template<T>

Page 25: Développer en natif avec C++11

une classe possède par défaut 5 opérations Un constructeur par copie Un opérateur de copie Un constructeur de move Un opérateur de move Un destructeur

Conseil si vous implémentez une de ces méthodes, alors implémentez-

les toutes.

Une classe C++11 type

Page 26: Développer en natif avec C++11

Conversion de enum automatiquement en int et enum fortement typé

enum Alert { green, yellow, election, red }; // traditional enum enum class Color { red, blue }; // scoped and strongly typed enum

// no export of enumerator names into enclosing scope // no implicit conversion to int

enum class TrafficLight { red, yellow, green }; Alert a = 7; // error (as ever in C++) Color c = 7; // error: no int->Color conversion int a2 = red; // ok: Alert->int conversion int a3 = Alert::red; // error in C++98; ok in C++0x int a4 = blue; // error: blue not in scope int a5 = Color::blue; // error: not Color->int conversion Color a6 = Color::blue; // ok

enum & enum classclass enum

Page 27: Développer en natif avec C++11

Indiquer explicitement un opérateur de copie par défault

class Y { // ... Y& operator=(const Y&) = default; // default copy semantics Y(const Y&) = default; }

Indiquer l’interdiction de la copieclass X { // ... X& operator=(const X&) = delete; // Disallow copying X(const X&) = delete; };

=default et =delete

Page 28: Développer en natif avec C++11

Le mécanisme de constexpr Permet d’exprimer généralement des

expressions constantes Permet d’utiliser les types spécifiques Fournit l’assurance que l’initialisation est fournie

au moment de la compilationAttention constexpr ne remplace pas const (et vice versa)

constexpr

Page 29: Développer en natif avec C++11

Le mécanisme de decltype(E) permet d’avoir une expression qui peut être utilisée dans une déclaration Concept utilisé en programmation générique Appelée aussi “typeof”

Conseil Préférez l’utilisation de auto

decltype(E)

Page 30: Développer en natif avec C++11

Maintenant, on peut écrire celavector<double> v = { 1, 2, 3.456, 99.99 };

list<pair<string,string>> languages = { {"Nygaard","Simula"}, {"Richards","BCPL"}, {"Ritchie","C"} };

map<vector<string>,vector<int>> years = { { {"Maurice","Vincent", "Wilkes"},{1913, 1945, 1951, 1967, 2000} }, { {"Martin", "Ritchards"} {1982, 2003, 2007} }, { {"David", "John", "Wheeler"}, {1927, 1947, 1951, 2004} } };

L’utilisation de {} est possible via une fonction (souvent par un constructeur) qui accepte un argument std::initializer_list<T>

vector (std::initializer_list<E> s) // initializer-list constructor

Initialisation des listes

Page 31: Développer en natif avec C++11

Si deux ctor font la même chose, il faut une routine init() et faire un appel dans chaque ctor…Maintenant, il est possible décrire cela

class X { int a; public: X(int x) { if (0<x && x<=max) a=x; else throw bad_X(x); } X() :X{42} { } X(string s) :X{lexical_cast<int>(s)} { } // ... };

Délégation de constructeur

Page 32: Développer en natif avec C++11

Seules les membres statiques peuvent être initialisés et avec des expressions constantes…Maintenant, il est possible décrire cela

class A { public: A() {} A(int a_val) : a(a_val) {} A(D d) : b(g(d)) {} int a = 7; int b = 5; private: HashingFunction hash_algorithm{"MD5"}; // Cryptographic hash to be applied to all A

instances std::string s{"Constructor run"}; // String indicating state in object lifecycle };

Init. de membres de classes

Page 33: Développer en natif avec C++11

Un type long mais qui est very long. Au moins 64 bits

long long x = 9223372036854775807LL;

long long (64 bits)

Page 34: Développer en natif avec C++11

Un typedef pour les templatesPermet une écriture plus élégante des templates dans le code

template<class T> using Vec = std::vector<T,My_alloc<T>>; // standard vector using my allocator Vec<int> fib = { 1, 2, 3, 5, 8, 13 }; // allocates elements using My_alloc

Marche aussi avec le code style-Ctypedef void (*PFD)(double); // C style using PF = void (*)(double); // using plus C-style type

template typedef

Page 35: Développer en natif avec C++11

Avant… vector<shared_ptr<CPolygon>>::iterator beg =

polys.begin(); long et fastidieux à écrire !

Maintenant, avec « auto » auto i = polys.begin(); Type déduit par le compilateur Equivalent de « var » en C# Evite aussi certaines conversions implicites en cas

d’erreur sur le type

auto

Page 36: Développer en natif avec C++11

map<string, string> m;const regex r("(\\w+) (\\w+)");for (string s; getline(cin, s); ) { smatch results; if (regex_match(s, results, r)) { m[results[1]] = results[2]; }}for (auto i = m.begin(); i != m.end(); ++i) { cout << i->second << " are " << i->first << endl;}// Au lieu de map<string, string>::iterator

auto

Page 37: Développer en natif avec C++11

auto utilise les règles de détection d’arguments des templates

const auto * p = foo et const auto& r = bar compilentauto... Réduit le code et améliore la lisibilité du code important Permet d’éviter les erreurs de types, troncations, … Améliore la généricité du code sans le superflu des

expressions intermédiaires Fonctionne très bien avec les types comme les lambdas

auto: pourquoi l’utiliser ?

Page 38: Développer en natif avec C++11

vector<int> v;

for (auto i = v.begin(); i != v.end(); ++i) { // i is vector<int>::iterator}

for (auto i = v.cbegin(); i != v.cend(); ++i) { // i is vector<int>::const_iterator}

cbegin(), cend(), crbegin(), crend()

Page 39: Développer en natif avec C++11

Les références de Rvalue permettent deux choses importantes : Déplacement (move semantics) : pour la performance Perfect forwarding: pour la généricité

= une seule fonction générique qui accepte des arguments quelconques et les transmet de manière transparente à une autre fonction en préservant leur nature (const, lvalue, rvalue, etc)

Ex : make_sharedLes patterns de déplacement et de perfect forwarding sont simples à mettre en oeuvreMais ils s’appuient sur de nouvelles règles d’initialisation, de résolution de surcharge, de déduction des paramètres des templates, etc.Les conteneurs STL sont “move aware”

Références de RValue

Page 40: Développer en natif avec C++11

set<widget> load_huge_data() { set<widget> ret; // … load data and populate ret … return ret;}widgets = load_huge_data();

Efficacité du déplacement

vector<string> v = IfIHadAMillionStrings();v.insert( begin(v)+v.size()/2, “tom” );v.insert( begin(v)+v.size()/2, “richard” );v.insert( begin(v)+v.size()/2, “harry” );

HugeMatrix operator+( const HugeMatrix&, const HugeMatrix&);hm3 = hm1+hm2;

Efficace: pas de copie en profondeur et pas

besoin du contournement

allocation dynamique + retour de pointeur

Efficace, pas de copie en

profondeur

(juste les assignements de

pointeurs

Efficace, pas de copie supplémentaire

Page 41: Développer en natif avec C++11

class my_class { unique_ptr<BigHugeData> data;public: my_class( my_class&& other ) : data( move( other.data ) ) { } my_class& operator=( my_class&& other ) { data = move( other.data ); } ::: void method() { if( !data ) throw “moved-from object”; ::: }};

Mécanique du Move / Value Types

move construction

move assignment

check (if appropriate)

Copy ? Move: Also enable move if it can be cheaper than a deep

copy.

Move / Copy: Some non-value types are naturally move-only.

Example: unique_ptr.

Page 42: Développer en natif avec C++11

<algorithm> bool all_of/any_of/none_of(InIt, InIt, Pred) InIt find_if_not(InIt, InIt, Pred) OutIt copy_n(InIt, Size, OutIt) OutIt copy_if(InIt, InIt, OutIt, Pred) bool is_partitioned(InIt, InIt, Pred) pair<Out1, Out2> partition_copy(InIt, InIt, Out1, Out2, Pred) FwdIt partition_point(FwdIt, FwdIt, Pred) bool is_sorted(FwdIt, FwdIt, Comp?) FwdIt is_sorted_until(FwdIt, FwdIt, Comp?) bool is_heap(RanIt, RanIt, Comp?) RanIt is_heap_until(RanIt, RanIt, Comp?) pair<FwdIt, FwdIt> minmax_element(FwdIt, FwdIt, Comp?)

<numeric> void iota(FwdIt, FwdIt, T)

<iterator> InIt next(InIt, Distance) BidIt prev(BidIt, Distance)

Nouveautés des algorithmes

Page 43: Développer en natif avec C++11

Parcours simples Exemple : for_each = le plus simple

Parcours avec transformations Exemple : copy = copie tous les éléments

répondant à une conditionTris Exemples : sort, stable_sort, lower_bound

Algorithmes : trois catégories

Page 44: Développer en natif avec C++11

All ofAny ofNone ofFor eachFindFind endFind firstAdjacent FindCountMismatchEqualIs permutationSearch

Parcours simples

Page 45: Développer en natif avec C++11

template<class InputIterator, class Predicate>InputIterator find_if(InputIterator first, InputIterator last, Predicate pred);

Retourne le premier élément vérifiant le prédicatPredicate : Fonctions prédéfinies Classe surchargeant operator() Lambda

Exemple : Find first

Page 46: Développer en natif avec C++11

CopyMoveSwapTransformReplaceFillGenerateRemoveUniqueReverseRotateRandom shufflePartitions

Transformations

Page 47: Développer en natif avec C++11

template<class InputIterator, class OutputIterator, class UnaryOperation>OutputIterator transform(InputIterator first, InputIterator last, OutputIterator result, UnaryOperation op);

Exemple: impression de tous les éléments d’un conteneur :

copy(points.begin(), points.end(), ostream_iterator<CPoint>(cout, "\n" ));

Exemple Transform

Page 48: Développer en natif avec C++11

SortStable_sortPartial_sortNth elementBinary search : lower_bound, upper_boundMerge

Tri et assimilés

Page 49: Développer en natif avec C++11

template<class RandomAccessIterator, class Compare>void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp);

Trie les éléments selon « comp »Comp = ordre strict (< ou > et non £ ou ³)

bool PlusHaut(CPoint &pt1, CPoint &pt2){ return pt1.Y() > pt2.Y();}sort(points.begin(), points.end(), PlusHaut);

Exemple : sort

Page 50: Développer en natif avec C++11

Fonctions simples pas paramétrables

Classes Lourdes à écrire Pb de localité

Lambdas Le meilleur des deux mondes

Lambdas

Page 51: Développer en natif avec C++11

Les Lambda Expressions définissent et construisent des classes fonctions anonymesLa Lamba Expressionfor_each(v.begin(), v.end(), [](int n) { cout << n << " "; });

Est équivalente àstruct LambdaFunctor { void operator()(int n) const { cout << n << " "; }};…for_each(v.begin(), v.end(), LambdaFunctor());

Le B.A. BA des lambdas

Page 52: Développer en natif avec C++11

Une lambda peut contenir plusieurs instructions

void par défaut

Lambda Stateless: [] signifie pas de capture du contexteCapture-list : utilisation de variables extérieures à la lambda

v.erase(remove_if(v.begin(), v.end(), [x, y](int n) { return x < n && n < y; }), v.end());

Les copies capturées « survivent » à leur contexte

Possibilité de capture par référence

Compléments

Page 53: Développer en natif avec C++11

Maintenant, on peut écrire celavector<double> v = { 1, 2, 3.456, 99.99 };

list<pair<string,string>> languages = { {"Nygaard","Simula"}, {"Richards","BCPL"}, {"Ritchie","C"} };

map<vector<string>,vector<int>> years = { { {"Maurice","Vincent", "Wilkes"},{1913, 1945, 1951, 1967, 2000} }, { {"Martin", "Ritchards"} {1982, 2003, 2007} }, { {"David", "John", "Wheeler"}, {1927, 1947, 1951, 2004} } };

L’utilisation de {} est possible via une fonction (souvent par un constructeur) qui accepte un argument std::initializer_list<T>

vector (std::initializer_list<E> s) // initializer-list constructor

Initialisation des listes

Page 54: Développer en natif avec C++11

Si deux ctor font la même chose, il faut une routine init() et faire un appel dans chaque ctor…Maintenant, il est possible d’écrire cela

class X { int a; public: X(int x) { if (0<x && x<=max) a=x; else throw bad_X(x); } X() :X{42} { } X(string s) :X{lexical_cast<int>(s)} { } // ... };

Délégation de constructeur

Page 55: Développer en natif avec C++11

Seules les membres statiques peuvent être initialisés et avec des expressions constantes…Maintenant, il est possible d’écrire cela

class A { public: A() {} A(int a_val) : a(a_val) {} A(D d) : b(g(d)) {} int a = 7; int b = 5; private: HashingFunction hash_algorithm{"MD5"}; // Cryptographic hash to be applied to all A

instances std::string s{"Constructor run"}; // String indicating state in object lifecycle };

Init. de membres de classes

Page 56: Développer en natif avec C++11

TESTS UNITAIRES DANS VISUAL STUDIO

Chapitre 2

Développement natif en C++ 11

Page 57: Développer en natif avec C++11

• Tests unitaires 100% natifs intégrés à l’IHM• Framework de test

– Fourni par Microsoft– Google tests– xUnit++– Autre ?

blogs.msdn.com/b/bhuvaneshwari/archive/2012/03/13/authoring-a-new-visual-studio-test-adapter.aspx

• Couverture de code

Tests unitaires natifs

Page 58: Développer en natif avec C++11

Programme (.exe)

Tests unitaires natifs : Architecture

Programme (.exe)

Bibliothèque 1 (.lib)

Bibliothèque 2

(.dll)

Tests unitaires 1

(.dll)

Tests unitaires 2

(.dll)

Exécuteur de tests (.exe)

Programme (.exe)

Page 59: Développer en natif avec C++11

VISUAL C++11 ET NOV 2012 CTPChapitre 3

Développement natif en C++ 11

Page 60: Développer en natif avec C++11

• CTP = Version version beta– Incomplet : Uniquement le compilateur (pas la

SL)– Pas pour utilisation en prod– Bugs possibles– Activé explicitement

• 6 nouveautés• Des démos !

Visual C++ compiler Nov 2012 CTP

Page 61: Développer en natif avec C++11

• 6 nouveautés– Littéraux de chaîne de caractères bruts– Initialisation uniforme et initializer_lists– Délégation de constructeurs– Opérateurs de conversion explicites– Templates variadiques– Arguments template par défaut pour les

fonctions template

Visual C++ compiler Nov 2012 CTP

Page 62: Développer en natif avec C++11

• Bénéfices– Code C++ plus simple, plus rapide à écrire– Meilleure compatibilité avec gcc, clang…• Code portable avec moins de restrictions• Plus large choix de bibliothèques

• À quand la version finalisée ?• Le chemin n’est pas fini…

Visual C++ compiler Nov 2012 CTP

Page 63: Développer en natif avec C++11

• N’oubliez pas : Le nouveau portail du C++ :

www.isocpp.org

Questions / Réponses

Page 64: Développer en natif avec C++11

The Space needle

Exemple de slide photo

Design

Page 65: Développer en natif avec C++11

Developpement

Exemple de code<common:LayoutAwarePage x:Name="pageRoot" x:Class="App3.GroupedItemsPage" DataContext="{Binding DefaultViewModel, RelativeSource={RelativeSource Self}}" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:App3" xmlns:data="using:App3.Data" xmlns:common="using:App3.Common" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">

Page 66: Développer en natif avec C++11
Page 67: Développer en natif avec C++11

Réseaux

• Exemple de Pie chart pour une session Réseaux

Exemple de graphe

Page 68: Développer en natif avec C++11
Page 69: Développer en natif avec C++11
Page 70: Développer en natif avec C++11
Page 71: Développer en natif avec C++11
Page 72: Développer en natif avec C++11
Page 73: Développer en natif avec C++11
Page 74: Développer en natif avec C++11
Page 75: Développer en natif avec C++11
Page 76: Développer en natif avec C++11
Page 77: Développer en natif avec C++11

Formez-vous en ligne

Retrouvez nos évènements

Faites-vous accompagner gratuitement

Essayer gratuitement nos solutions IT

Retrouver nos experts Microsoft

Pros de l’ITDéveloppeurs

www.microsoftvirtualacademy.com

http://aka.ms/generation-app

http://aka.ms/evenements-developpeurs

http://aka.ms/itcamps-france

Les accélérateursWindows Azure, Windows Phone,

Windows 8

http://aka.ms/telechargements

La Dev’Team sur MSDNhttp://aka.ms/devteam

L’IT Team sur TechNethttp://aka.ms/itteam