Citation:
Envoyé par
Nemek
Je parlais surtout des pointeurs dont il faut faire particulièrement attention. Alors peut-être qu'avec le temps ca devient ultra intuitif en ayant des patterns simples et efficaces ; en attendant on doit focaliser une part d'attention à ça, ce qui nous prive de nous focaliser sur autre chose. C'est bien ça qu'offre des plateformes comme Java et .Net
Oui et non. C'est vrai qu'en C++ le développeur se doit de réfléchir à la durée de vie de ses objets (même si les smarts pointeurs permettent de se simplifier la vie, il reste néanmoins à les utiliser correctement). Après ce n'est pas parce que je dois penser à cela que je ne pense pas au reste. Mais c'est vrai que c'est une charge supplémentaire.
Citation:
Et quand je vois le nombre d'applications qui se terminent en Core Dump, je me dis que tout le monde ne les manipules pas si bien que ça.
Cependant il n'est pas rare des applications Java qui ont de graves fuites mémoires (surtout en environnement modulaire).
Ce qui montre que l'on doit quand même y réfléchir un minimum même en java (et contrairement à ce que l'on pourrait croire de prime abord).
Tiens à ce sujet, un petite question :
Existe-t-il en java un equivalent au destructeur en c++? Parce qu'en ce qui concerne la gestion des ressources (pas seulement de la mémoire mais aussi tout ce qui est accès à un fichier, connexion réseau, thread, ...) je trouve que c'est quelque chose de quasi indispensable.
Citation:
La permissivité (ou le laisser-aller/faire) ne sont pas, par expérience, didactique. Au contraire, plus tu laisses de liberté aux gens et plus ils en prennent plus que d'être ultra-rigoureux.
Et plus on leur tapes dessus ensuite parce qu'ils ont fait n'importe quoi :aie:
Citation:
Non ca me choque pas car
- ce n'est pas à nous de déterminer si une infinité d'objet dans une infinité de contexte ont un lien ou pas.
- si je veux les mettre dans un même panier c'est que je considère qu'il existe un lien
- dans le cas de Java et des collections, ca rend le code générique, compatible avec toutes les classes et légèrement optimisé
Sauf que dans le contexte d'un programme donné, 2 objets peuvent avoir un lien ou ne pas en avoir. Si l'on reprend l'exemple des voitures, on peut très bien concevoir avoir une voiture, un camion ou un vélo dans une même liste. Par contre, je peux très bien considérer qu'un feux de signalisation n'a rien à y faire. Aussi je préfère que ce soit mon compilo qui m'envoie balader parce que je me suis trompé à un moment dans mon code plutot que de devoir tester mon appli puis chercher pendant des heures pour me rendre compte de mon erreur.
Après, je me trompe peut-être mais les generics en java doivent permettre d'arriver au même résultat non? (j'entends par là une erreur à la compilation). Dans ce contexte, j'aurai même tendance à dire que le fait que tout object hérite de la classe object etait surtout une nécéssité à une époque ou les générics n'existaient pas encore.
Quoi qu'il en soit, je considère perso que toute map, liste ou autre conteneur se doit d'être typés un maximum (via les générics en java et les templates en C++) et que les conteneurs contenant des objects sont à proscrire.
Enfin, je dirai qu'il ne faut pas forcément que tout soit objet pour pouvoir avoir un code générique. Après tous, les conteneurs de la STL y arrivent très bien.
Citation:
J'admet volontiers qu'il n'y a pas de nécessité d'avoir une base unique. Je dis en revanche que cela a ses avantages. Cela sert la cause de Java et non le contraire. Quiconque manipule un peu l'API se rend compte qu'Object n'est pas dénué de sens et de fonctionnalité contrairement à void.
N'oublie pas non plus que Object possède une méthode getClass() (qui remettra sûrement cause beaucoup de piliers de OO) qui permet d'en savoir beaucoup sur une instance donnée.
Pour ce qui est de void* (et non void ;)), son utilisation est à proscrire autant que possible.
Pour la méthode getClass, le C++ utilise un opérateur pour obtenir le type d'une variable donnée. Après, il est clair que les possibilités en la matière en c++ sont très limitée. Mais bon. Je ne suis pas un fan de la reflection de toute façon.
Citation:
Je suis peut-être un peu bisounours aussi dans l'âme mais je pense que quelqu'un de son "niveau" doit être apte à comprendre OO, d'autant plus s'il se permet d'y porter un jugement de valeur. Bon après je connais pas du tout le type ; je veux pas dire personnellement mais dans l'ensemble (l'image qu'il dégage, etc). C'est peut-être un petit con : tu me confirmeras ou pas !
Bof, perso quand je vois ce qu'il a écrit, j'ai quand même quelques doutes. En fait, j'ai un peu l'impression qu'il jette le bébé avec l'eau du bain. Tout n'est pas parfait en C++, mais quand on le compare avec le C, le C++ apporte quand même beaucoup de facilités je trouve. (le problème étant qu'il n'est pas toujours facile de toutes les maitriser).
Citation:
Bah dans une "Reference Map", je vois aucune obligation d'avoir des clés homogènes
Ben désolé mais moi j'en vois une!
Si je veux par exemple utiliser un id (donc un int) afin de stocker différents éléments dans ma map, j'apprécie que mon compilo vérifie ce fait et me prévienne si jamais à un moment donné j'essaie d'y mettre autre chose qu'un entier.
Après, il est possible que l'on veuille pouvoir utiliser n'importe quoi comme clé dans un cas précis, mais si je sais à l'avance que je n'y pettrai que des entiers, je préfère que mon compilo le vérifie.
Citation:
Pour information (et désolé du sacrilège de la syntaxe) mais est-ce que le code suivant compile ?
Code:
1 2 3 4 5
| Foo* foo = ...;
Bar* bar = ...;
if (foo == bar) {
...
} |
Je viens de tester avec le code suivant :
Code:
1 2 3 4 5 6 7 8 9 10
|
int main()
{
int *a;
double *b;
if(a == b)
return 0;
else
return 1;
} |
J'obtient ceci:
test.cpp: In function ‘int main()’:
test.cpp:5:10: error: comparison between distinct pointer types ‘int*’ and ‘double*’ lacks a cast [-fpermissive]
donc non cela ne compile pas (ce qui est à mon sens une bonne chose).
Par contre, le code suivant compile :
Code:
1 2 3 4 5 6 7 8 9 10 11 12
|
int main()
{
int x = 3;
double y = 5;
void *a = &x;
void *b = &y;
if(a == b)
return 0;
else
return 1;
} |
Citation:
Les templates, pwaaa. Et toutes façons ils vont supposer (comme les langages dynamiques) que les membres utilisés existent. Si je prends le cas des HashMap, ton code va supposer que les types qui vont "instancier le template" (?) dispose bien des méthodes de calculs du hash et de comparaison sans qu'ils aient de point commun. Tu ne fais que déclarer des interfaces implicites.
Tout à fait, et si un membre n'existe pas, on a une erreur à la compilation. C'est par ailleurs tout le sujet des concepts. (car actuellement, quand un membre n'existe pas l'erreur générée par le compilo est difficelent lisible, surtout pour un néophyte).
Citation:
Concernant le paradigme générique (s'il s'agit bien de la même chose qu'en Java), il faut bien un point commun. D'ailleurs c'est la raison de la présence de Boost::Any non ?
Je ne sais pas si c'est le même qu'en java. Mais s'il doit y avoir un point commun, je dirai qu c'est le fait qu'un type donné respecte ou pas tel ou tel concept (lesquels peuvent être vu comme tu l'a fort justement dit comme des interfaces implicites). Cependant les concepts ne font pas (encore) parti du langage.
Citation:
Que tu colles ta fonction/procédure dans un namespace Foo::Bar ou une méthode dans une classe foo.Bar, je vois pas la différence :x
Si ce n'est que comme dit plus haut les namespaces sont extensibles. Mais c'est vrai qu'au final cela ne change pas grand chose. (Par ailleurs, il m'arrive parfois de préférer avoir des méthodes statiques contenues dans une classe plutot que de les avoir au niveau du namespace.)
En espérant avoir contribué à faire avancer la discussion :D