Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

[debat] Le mots clef const

Le , par Dr Dédé

0PARTAGES

2  3 
ceci est un fork de la discution
pointeurs intelligents vs pointeurs bruts


Salut,

a- ce n'est pas une idée préconçue, mais l'état actuel de mon opinion sur le sujet, opinion induite par mes expériences.
Je perds plus de temps à traquer des dérèglements induits par les laxismes des C&C++ qu'à comprendre les erreurs de compilation qui me sont sortis.
Et franchement, ce ne sont pas quelques const, quelques références, voire des volatiles (cf le détournement du mot clé par A.Alexandrescu), et autres invariants d'immuabilité pour vont me causer des complications pour compiler.
Le problème avec const c'est que, de 1) ça ne marche pas, 2) ça n'offre aucune garantie réelle, 3) ça se propage à tout ce que ça touche.

Exemple de 1):

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
void MaFonction(const vector<const T*>& vecteur)
{
}

int main()
{
	vector<T*> vecteur;
	MaFonction(vecteur);
}
Pourquoi est-ce que ça ne compile pas? Je promets pourtant de ne pas modifier ni le vecteur ni les éléments qu'il contient. "Solutions" possibles: (i) je créé un vecteur de const T* temporaire (ii) je créé une version non-const de la fonction, duplicant ainsi le code et perdant toute garantie d'immutabilité sur le contenu du vecteur, ou (iii) je ne garde qu'une version non-const de la fonction et je ne m'en porte pas plus mal.

Exemple de 2):

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
class MyObject {
	mutable int a;
	int b;
public:
	void ConstMethod1() const { a = 3; }
	void ConstMethod2() const { ((MyObject*)this)->b = 3; }
};

int main() {
	const MyObject o;
	o.ConstMethod1();
	o.ConstMethod2();
}
Les deux fonctions const modifient l'objet, et pas même un warning de compilateur. Quelle garantie offre donc const? Uniquement celle que je m'engage à respecter.

Exemple de 3)
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;

class MyObject {
	int speakUpCounter;
	void SayHello() { cout << "Hello!\n"; }
	void SayWatsup() { cout << "WAZA!\n"; }
	void SayBye() { cout << "Bye!\n"; }
public:
	MyObject() : speakUpCounter(0) {}
	void SpeakUp() { SayHello(); SayWatsup(); SayBye(); ++speakUpCounter;}
};

int main() {
	MyObject o;
	o.SpeakUp();
}
Voici une jolie petite classe qui marche très bien. Elle compte le nombre de fois que SpeakUp() a été appelé. Tout va très bien jusqu'au jour où je veux la passer à cette fonction:

void DoSomething(const MyObject& o) { o.SpeakUp(); ... }

Et tout à coup, erreur de compil, SpeakUp n'est pas const. Bon, je rends SpeakUp const, pas de problème. 3 erreurs de compil, SayHello, SayWatsup et SayBye ne sont pas const non plus. Bon, je les rends const aussi. 1 erreur de compil: speakUpCounter est modifié. C'est un compteur interne qui ne fait pas sémantiquement partie de l'état de mon objet, donc je le rends "mutable". Et ici ça va compiler après seulement peut-être 10 minutes de recompilation / réflexion parce que l'exemple est très simple, mais imaginons un instant que MyObject utilise un méthode non-constante d'un autre objet... je suis obligé d'aller modifier cet autre objet, et on n'en finit plus. Ensuite, se rend-on bien compte du ridicule d'un mot-clé "mutable" dans un langage où tout est mutable par défaut? Ne perd-on pas un temps absurde à ajouter const partout alors que l'immutabilité est loin de constituer un souci important en bien des cas? Ne nuit-on pas sévèrement à la lisibilité du code? Combien de temps faut-il pour déchiffrer
Code : Sélectionner tout
const char* const Func(const int* const, const float* const) const;
et se rendre compte que cela veut dire
Code : Sélectionner tout
char* Func(int*, float*);
Ensuite, d'expérience, j'ai travaillé sur des bases de code inondées de const autant que d'autres sans const du tout, et la seule différence que j'ai pu voir c'est que les dernières sont nettement plus lisibles et maintenables. Les deux types étaient tout autant bourrées de bogues. Voilà donc pour const.

Pour les références, j'ai suffisamment argumenté et illustré qu'elles n'apportent rien de plus que les pointeurs si ce n'est une certaine légèreté syntaxique. Je comprends l'argument que les références apportent une sécurité accrue, mais pouvez-vous illustrer vos propos?

Le C++ est loin d'être le seul langage que nous connaissons. Comment le maitriser si on ne connait que lui et le C?
Je n'accuse personne ici de ne connaître que C et C++. Je fais simplement remarquer que C++ est le plus souvent comparé à C et que c'est une comparaison très limitée. Nous sommes d'accord alors tant mieux.

Je n'utilise jamais at(). Mais vraiment. Jamais. Je la vois comme une fonction pour faire plaisir. En ce qui me concerne, elle n'existe pas. Mon seul point d'entrée est operator[], et j'ai une nette préférence pour ses implémentations qui claquent une assertion sur dépassement de bornes -- pour la raison que j'ai citée: se planter dans les bornes, c'est une erreur de programmation. Malheureusement, ce n'est pas spécifié ainsi.
Mon point initial, c'est que tu dois garantir toi-même qu'une référence est valide, ce n'est pas le compilateur qui va le faire. Que tu utilises une exception ou une assertion, c'est comme tu veux. Pour l'opérateur[], le contrat c'est "si l'élément existe, je retourne une référence valide, sinon, tout explose." Et faire tout exploser est une stratégie comme une autre pour s'assurer qu'une référence invalide n'existe pas. Mais encore une fois, ce n'est pas le compilateur qui implémente cette stratégie, c'est le concepteur de la librairie. Donc, la référence n'offre pas de garantie particulière par rapport au pointeur.

b- 20 d'expérience en C++ n'est pas exactement un critère au vu des révolutions perpétuelles dans ses paradigmes
Bon, alors puisqu'il faut le mentionner, programmeurs qui se servent quotidiennement des templates et qui lisent Alexandrescu et Herb Stutter pour s'endormir. S'ils ont de la difficulté à résoudre une erreur de compilation, c'est peut-être qu'une erreur de compilation n'est pas forcément facile à régler, est-ce si dur à admettre?

malgré la compétence de ceux qui mettent les test unitaires au point et la qualité de ceux-ci, tout ce qu'ils prouvent, c'est que l'on n'a pas été en mesure de prendre les parties testées en faute, absolument pas que les parties testées sont exemptes d'erreur
Mais utiliser une référence ne prouve pas qu'elle est valide, utiliser const ne prouve pas que l'objet const n'est pas modifié, etc. Un test unitaire prouve à tout le moins qu'un certain cas d'utilisation passe, tandis que les références et const ne prouvent strictement rien. Si je déplace l'investissement mental de me demander quels pointeurs peuvent être remplacés par des références et quels types et fonctions peuvent être déclarés const, par des test unitaires additionnels, j'arrive un niveau de confiance bien supérieur, forcément.

Une erreur dans cette actualité ? Signalez-le nous !

Avatar de Joel F
Membre chevronné https://www.developpez.com
Le 26/10/2010 à 8:11
je vais juste reprendre la partie sur const qui me semble mal amené

Exemple de 1):

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
void MaFonction(const vector<const T*>& vecteur)
{
}

int main()
{
	vector<T*> vecteur;
	MaFonction(vecteur);
}
Le probleme ne vient pas de const mais du fait que vector<T> et vector<U> n'ont aucun lien sémantique. Plainds toi auprès de la spec des templates mais pas de const. Tu aurais le même problème avec A et B héritant de A.

Exemple de 2):

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
class MyObject {
	mutable int a;
	int b;
public:
	void ConstMethod1() const { a = 3; }
	void ConstMethod2() const { ((MyObject*)this)->b = 3; }
};

int main() {
	const MyObject o;
	o.ConstMethod1();
	o.ConstMethod2();
}
Si tu ecris du code moche avec des cast improbables, tout est possible.
Je vois ça passer dasn un commit, l'ingé qui à pondu ça est mis à pied . Exemple rejeté :o

Exemple de 3)
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;

class MyObject {
	int speakUpCounter;
	void SayHello() { cout << "Hello!\n"; }
	void SayWatsup() { cout << "WAZA!\n"; }
	void SayBye() { cout << "Bye!\n"; }
public:
	MyObject() : speakUpCounter(0) {}
	void SpeakUp() { SayHello(); SayWatsup(); SayBye(); ++speakUpCounter;}
};

int main() {
	MyObject o;
	o.SpeakUp();
}
Deux choses:

- le speakupCounter doit etre mutable par design. Il ne participe pas à la sémantique de l'objet et donc peut etre modifié par des méthodes const.
Ca compile et marche très bien comme ça:

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;

class MyObject {
	mutable int speakUpCounter;
	void SayHello() const { cout << "Hello!\n"; }
	void SayWatsup() const { cout << "WAZA!\n"; }
	void SayBye() const { cout << "Bye!\n"; }
public:
	MyObject() : speakUpCounter(0) {}
	void SpeakUp() const { SayHello(); SayWatsup(); SayBye(); ++speakUpCounter;}
};

int main() {
	MyObject o;
	o.SpeakUp();
}
les méthodes SayXXX sont forcément const par design et non par effet de bord. Le reste en découle tout seul.

- jamais j'implante ça comme ça. Le fait de SpeakUp et de compter sont 2 choses différentes. Ca manque d'un Observer quelque part pour séparer les responsabilités.

Je rebondis ensuite sur "babababa les templates ca fait des messages moches". Ca a au moins l'avantage d'en emettre des messages d'erreurs (oui je vous regarde les macros C au fond là). Ensuite, si à l'époque de la STL des choses comme STATIC_ASSERT ou du vrai Concept Checking avaient été là, il aurait fallu l'en tartiner. J'ai plusieurs bibliothèques qui utilisent ça, et le pire erreur qui en remonte fait 2 lignes et pointe exactement la ou il faut. Ensuite stlfilt et boost marche assez bien ensemble si VRAIMENT ca vous dépasse.

Sinon pour la guerre de religion pointeur/reférence. Personne n'est mieux que l'autre, il y a juste des cas d'utilisations naturelles qui sont guidés par le design de l'API.

Voila :o
6  0 
Avatar de gl
Rédacteur https://www.developpez.com
Le 28/10/2010 à 8:53
Citation Envoyé par Dr Dédé Voir le message
Mais mon exemple donnerait exactement la garantie dont tu parles. Je vais illustrer:

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class IDisplayable {
public:
    virtual void Display() = 0;
};

class MyType : public IDisplayable {
public:
    void Display() { /* code qui ne modifie pas l'objet */ }
    void Initialize() { /* code qui modifie l'objet */ }
};

void DoStuff(IDisplayable* displayable) {
    // Cette fonction ne peut pas modifier l'objet!
    displayable->Display();
}

void DoOtherStuff(MyType* myType) {
    // Cette fonction peut modifier l'objet!
    myType->Initialize();
}
Plutôt que de noter Display() comme const, tu en fais une interface. Et pour la fonction qui ne doit pas modifier l'objet, au lieu de prendre une référence const, elle prend une référence sur cette interface. Le résultat est le même. Les avantages par rapport à const sont les suivants:
- Les contraintes d'immutabilité sont localisées: aucune propagation forcée à d'autres classes
- Les contraintes spécifiées par l'interface sont flexibles: je définis l'interface, donc je définis exactement ce que la fonction DoStuff peut faire. Je ne suis pas limité à la dichotomie const/non-const.
- L'idiome est commun à la plupart des langages orientés-objets
Et qu'est ce qui empêche ici de faire une fonction Display() qui modifie l'objet ?

J'ai l'impression que tu ne vois pas l'intérêt de const car tu pars du principe que le développeur de ta fonction "constante" ne va par commettre d'erreur dans celle-ci et que cela suffit à garantir l'immutabilité.
Malheureusement, ce n'est pas vrai, on fait tous des erreurs, ne serait-ce que d'étourderie.
Un des buts de const est justement, de mon point de vue, de détecter rapidement et tôt ce style d'erreur. Alors effectivement il est possible de contourner le const avec un const_cast mais c'est alors un choix volontaire et assumé, plus une simple erreur d'étourderie et const a bel et bien rempli son rôle.
6  0 
Avatar de 3DArchi
Rédacteur https://www.developpez.com
Le 30/10/2010 à 6:47
Citation Envoyé par Dr Dédé Voir le message
il ne peut pas contourner le fait que la vitesse de compilation du C++ est comparable à celle d'une limace constipée.
Ceci dit, les projets aux quels j'ai été confrontés et pour lesquels la vitesse de compilation était problématique était souvent des projets à l'architecture bancale (pour ne pas dire plus) amenant à des dépendances entre les différents modules qui n'auraient pas du être. Bref, un beau plat de spaghetti. Rien à voir avec le langage Pour voir actuellement des collègues transpirer sur du C#, je ne suis pas persuadé que l'assertion 'pour de l'embarqué/critique faite du C++, sinon utiliser un autre langage' soit très pertinente. La difficulté des projets tient (à mon avis) d'abord à la difficulté à saisir le besoin et à la complexité des systèmes mis en œuvre. Le langage n'a qu'une faible part et ses caractéristiques comme la const-correctness sont plus une aide qu'un poids mort (comme le dit screetch plus haut, en substance, le langage, s'il est compris, est plus une aide alors que si on se bat avec cela devient un boulet).
6  0 
Avatar de gbdivers
Inactif https://www.developpez.com
Le 26/10/2010 à 11:41
Quelle garantie offre donc const ? Uniquement celle que je m'engage à respecter.
C'est déjà pas mal, non ?

Ce n'est pas parce que le C++ autorise à ignorer un const (avec un simple const_cast ou un mutable ou autre) qu'il faut rejeter les const pour autant.

Si on part du principe que c'est le design qui définit où l'on doit mettre des const, alors ça permet de vérifier à la compilation que le code respecte bien le design. En cas de problème de const (ou en cas d'utilisation de const cast), on a affaire soit à un oubli de const quelque part, soit à un non respect du design.

Dans le code de l'exemple 3, le problème provient surtout (à mon avis et à priori celui de Joel F) du fait que tu n'avais pas mis des const, alors que ceux-ci auraient du être présent pour respecter le design. On est d'accord pour dire que mettre les const en fonction des erreurs de compilation donne plus de travaille que sans les const mais si on place les const en fonction du design, ça donne moins de travaille et c'est plus sur.

Donc on peut faire sans, mais si on fait avec, ça permet de valider (en partie) le code à la compilation.

Idem pour les références : on peut faire sans, mais si on les utilises correctement, ça apporte une vérification supplémentaire.
5  0 
Avatar de Joel F
Membre chevronné https://www.developpez.com
Le 27/10/2010 à 8:46
Faudrait voir à prendre la chose dans le bon sens ...
Personne ne va changer ces habitudes sur const, ni toi ni nous.
Je réitére juste que designé avec const en tête n'est pas plus dur ou plus illisible.
2  0 
Avatar de yan
Rédacteur https://www.developpez.com
Le 28/10/2010 à 9:39
Citation Envoyé par Dr Dédé  Voir le message
...Non. Quel est le rapport?

ce que tu montre ce sont des accesseur avec des accés qui permettent de modifier l'objet retourné. Donc oui il te faut dupliquer. Mais à part ce cas je ne voie pas pourquoi il faudrait doubler les fonctions à cause du const.

Citation Envoyé par Dr Dédé  Voir le message
Mais mon exemple donnerait exactement la garantie dont tu parles. Je vais illustrer:

non.Avoir une classe Immuable et avoir accès à une instance de manière immuable ne sont pas la même chose.

J'ai une classe interface IA
Code : Sélectionner tout
1
2
3
4
5
class IA 
{ 
public : 
  virtual void DOSomething(vector &) = 0  
}
Le vecteur passé en paramètre ne doit pas être modifié.
Mais sans ce const, rien n'êmpêche de faire une classe B qui initialise mon vecteur à 0
Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
public B : public IA 
{ 
   void DOSomething(vector &)  
   { 
      for(int i =0; i< v.size(); ++i) 
      { 
          v[i] = 0; 
      } 
   } 
}
alors que
Code : Sélectionner tout
1
2
3
4
5
class IA 
{ 
public : 
  virtual void DOSomething(const vector &) = 0  
}
Me l'aurais empêché.

Une entrée dans GOTW :
http://gotw.ca/gotw/006.htm
2  0 
Avatar de koala01
Expert éminent sénior https://www.developpez.com
Le 30/10/2010 à 4:47
Citation Envoyé par Dr Dédé Voir le message
Je n'ai pas le temps de répondre en détail à tous ceux qui m'ont répondu depuis la dernière fois, mais j'ai pensé à un truc ce matin. C++ est le seul langage que je connaisse où il existe ce concept de "const-correctness" et je m'y suis toujours opposé comme étant un ennui parmi d'autres de ce langage. Néanmoins, je peux comprendre comment la solution qui prévaut ailleurs (types immuables, encapsulation par accesseurs virtuels, etc.) n'est pas forcément satisfaisante en C++. En effet, difficile de travailler avec des types immuables dans un environnement non géré, et le coût des fonctions virtuelles est loin d'être nul (principalement parce qu'une méthode virtuelle ne peut pas être inline). Cette solution ne serait donc pas applicable dans les domaines de prédilection du C++, soit les systèmes embarqués, temps réel, haute performance (jeux vidéos), systèmes d'exploitation, etc, parce que dans ces contextes chaque cycle cpu compte: pas question que chaque accès à une donnée entraîne un appel de fonction virtuelle ou la création d'un nouvel objet.
Oui, c'est une des raisons...

Une autre étant, comme je l'ai expliqué plus haut, que le principe d'interface est sympa, mais qu'il ne faut pas non plus en abuser, du moins, lorsque le langage permet de s'en passer.

Je vais garder pour moi mon opinion sur les langages qui institutionnalisent le recours aux interfaces parce que c'est largement hors sujet (et qu'il y a déjà des débats sur les qualités et les défauts comparés de ces langages entre eux ou par rapport à C++ ), mais il faut avouer qu'une interface n'étant jamais qu'une classe (ou une structure) en C++, leur généralisation nous fait assister à une véritable explosion au niveau du nombre de classes que l'on a à gérer, et qu'une telle explosion est forcément contre productive.

Elle n'apporte rien en terme de sécurité en C++ et, malgré tout, apporte une complexification globale du projet qui, se répercutera, fatalement, sur les coups de développement et de maintenance.

Et nous sommes bien d'accord sur le fait que je ne dis pas qu'il ne faut pas utiliser les interfaces, mais que je dis qu'il faut les utiliser... à bon escient
const a donc l'avantage de ne rien coûter à l'exécution. Et là où la performance n'est pas si importante, on ferait mieux d'utiliser autre chose que C++.
Heeuuu... oui, mais non...

Oui, dans le sens où il faut reconnaitre que C++ est un langage complexe, difficile à maitriser, et qu'il est donc "facile" de trouver des langages dans lesquels les gens seront plus rapidement productifs.

Non, parce que... "qui peut le plus peut le moins".

Si tu as affaire à quelqu'un de compétant en développement et à un codeur qui maitrise le langage, il ne sera pas plus lent à fournir un résultat que quelqu'un ayant choisi un autre langage.

Et comme les performances seront généralement meilleures que ce que tu souhaites, tu n'aurais pas beaucoup de raisons de te plaindre

Mais bon, les égouts et les couleuvres en terme de langage préféré, cela ne se discute pas
De ce point de vue, const a donc sa place dans le langage.
Enfin...

Il ne reste plus qu'à te convaincre de l'utilité des références, pour se dire que l'on n'a pas perdu notre temps avec toi, et pour pouvoir espérer que tes développement futurs en C++ gagnent en qualité (je ne juge pas ici de la qualité de tes développement passés pour la cause, hein )
2  0 
Avatar de koala01
Expert éminent sénior https://www.developpez.com
Le 30/10/2010 à 5:05
Citation Envoyé par Dr Dédé Voir le message
En C#, Anders Hejlsberg a déjà répondu à cette question:
http://www.artima.com/intv/choicesP.html
En résumé: 1) const ne fonctionne en C++ que parce qu'on peut le contourner (const_cast); 2) const conduit à avoir des versions const de tout ce qui n'est pas const, créant ainsi une duplication (ce qui n'est pas si problématique en C++ à cause de 1)).
Mr Heilsberg est peut être une pointure en C#, mais je me permet d'émettre quelque doutes quant à sa compétence en C++ "moderne"

Si j'admets qu'il est parfois utile de dupliquer une fonction déclarée constante dans une version non constante, c'est loin d'être le cas général.

C'est, effectivement, utile lorsque tu veux renvoyer des itérateurs sur des collections, et encore, il m'arrive régulièrement de n'exposer que des fonctions (constantes) permettant de récupérer des itérateurs... constant, simplement parce qu'il n'y a aucun sens à permettre d'en obtenir d'autres

De même, le const-cast est, certes utile, mais son usage est particulièrement loin d'être généralisé.

A titre personnel, je suis par exemple loin de l'utiliser une fois en moyenne par unité de compilation: si je l'utilise une fois sur vingt ou sur cinquante unités de compilation, ca doit déjà faire beaucoup

Maintenant, je suis peut être une exception sur ces points, mais j'en serais assez surpris
2  0 
Avatar de Goten
Membre chevronné https://www.developpez.com
Le 01/11/2010 à 10:43
Citation Envoyé par Dr Dédé Voir le message
Clairement, ni l'un ni l'autre n'a lu l'article dont vous parlez. Guillaume07, parce que le lien était brisé et que tu ne l'as pas remarqué, j'en conclus que tu n'avais même pas essayé de cliquer dessus; Joel, parce que c'est tout sauf un benchmark sans valeur posté pour attirer l'attention, c'est la conclusion d'une série d'articles postés par Raymond Chen .
Et il est clair que tu n'as pas lu les articles de Raymond Chen justement... Il a benché les IO, je vois pas en quoi c'est généralisable aux C++ tout entier. (d'autant plus qu'on le sait tous les IO sont vraiment le point faible du C++ et ils sont lent il faut bien le dire, c'est d'ailleurs ce que M. Chen voulait démontrer).
2  0 
Avatar de zul
Membre éclairé https://www.developpez.com
Le 02/11/2010 à 9:43

Certainement. Mais dans bien des langages, il faut des besoins plus spécialisés que "je dois afficher quelque chose à l'écran" pour avoir à sortir de la librairie standard. Et donc, le problème existe ailleurs, mais dans une moindre mesure.
Marrant, personnellement, quand je compte les langages qui viennent avec une interface graphique dans leur librairie standard, je m'arrête assez vite. Allons y : java, java, hum smalltalk, et allez soyons généreux D. go / python / ruby / perl / php / js / erlang / haskell / ocaml / scheme / common lisp ... utilisent des librairies externes, et des bindings C/C++.

Quand tu regarde un environnement intégré comme gnome, tu trouve du C, du C++, du C#, du js, du python, du ruby, et j'en oublie certainement. Pas uniquement du C et C++. Le C et le C++ sont là pour batir les fondations (c'est un peu comme le CLR de .Net, mais en natif). Neaucoup de choses de haut niveau sont réalisés dans des langages de plus haut-niveau. Je connais aussi un certain nombre de jeux, sans forcément beaucoup de prétention, batis sur python / SDL.

Quand à la portabilité, la jvm ou mono est aussi rempli de #ifdef #endif (mince c'est écrit dans des langages bas-niveau en plus). Qt et/ou Boost ont fait ce travail pour toi, et propose des interfaces portables (ou Poco, ACE, ...). Du point de vue des développeurs utilisateurs de ces librairies, quelle est la différence ?

Pas compris ta réponse sur WPF, je répondais juste aux inexactitudes de tes propos : 1/ WPF c'est génial mais ce n'est pas portable 2/ l'utilisation de Qt ne t'oblige pas à releaser ton code ton GPL 3/ qu'est que fait WPF de si merveilleux ?
2  0