Il va chopper le pointeur vers la méthode dans la vtable référencée par chaque instance d'objet, donc j'imagine que les performances sont comparables à ce que tu faisais avant.

, et plus precisement, il y aura quand meme une petite difference, il y aura deux dereferencements de pointeurs (avec une vftable en C++) au lieu d'un seul (avec ta version C), mais point de vue taille, tu n'aura que sizeof(void*) octets de plus par objets en C++ contre sizeof(void*) * le nombre de pointeurs sur fonctions en C.
(un pointeur vers la vftable, et un autre pointeur dans la vftable vers la fonction)
Aze:
ah et tant qu'on en est à parler de méthodes virtuelles, pense aussi à déclarer tes destructeurs comme étant virtuels si tu ne veux pas avoir de mauvaises surprises 
brunni> autre precision histoire que tu le fasses pas sans savoir pourquoi

(ou que si une "mauvaise surprise" en rapport avec ca t'arrive tu ne te demande pas d'ou elle vient, ou que si t'as pas envie que ca se comporte comme ca, tu puisse quand meme ^^) : quand tu construis ta classe avec un new, ca sera forcement avec la classe la plus specialisee que tu veuille avoir (si tu veux un objet Piece, tu vas faire un "new Piece", pas un "new Objet", a priori

), donc lors de l'appel du constructeur, le compilateur peut savoir, au compile-time, suivant l'arbre d'heritage (qu'il connait de facon sure, vu qu'il connait le type exact: "Piece"), quelle liste de constructeurs appeler ("Objet(), Piece()").
par contre pour la destruction, vu que tu peux vouloir detruire une liste de pointeurs vers des base classes via une methode generique qui n'a pas connaissance des types specialises, si tu ne rends pas tes destructeurs virtuels, la destruction ne commencera qu'a partir du type visible lors de la destruction.
donc en gros, pour ton exemple d'au dessus, si tu fais des "new Piece()", que tu stockes ca dans une liste d'Objet*, et qu'apres tu delete chaque objet dans la liste, ca n'appellera que le destructeur d'Objet, pas le destructeur de Piece pour les objets qui sont effectivement des pieces...
hm aussi, si tu ne veux obliger les classes qui derivent de Objet a implementer certaines methodes, au lieu de definir des methodes vides dans Objet tu peux les rendre virtuelles pures:
genre ca:
virtual void draw() = 0;
au lieu de:
virtual void draw() {}
ca petera une erreur a la compilation si t'essaye d'instancier Objet ou une classe qui derive d'Objet mais qui n'a pas defini draw()... bref...
et dans Piece tu mets:
class Piece
{
...
virtual void draw() override
{
oslPrintf_xy(0, 8, "PIECE");
Objet::draw();
}
};
"override" est facultatif, mais ca fait juste gueuler visual si jamais tu change la methode dans la classe de base en oubliant de changer celle dans la classe derivee, sans override ca compilerait silencieusement, en supposant que la methode dans la classe derivee est soit une nouvelle methode, soit un overload de la methode de la classe de base, suivant la modification... la, avec override, ca te sort un truc dans les lignes de "draw did not override any base class method, bla bla..."
par contre je sais pas si override est portable, mais bon c'est pas genant, et c'est quand meme bien pratique de l'avoir quand tu dev sous visual... au pire tu fais un
#if !defined(_MSC_VER)
#define override
#endif
pour que ca passe quand c'est pas compile avec visual