Fonctions dynamiques

De RAD Studio
Aller à : navigation, rechercher

Remonter à Fonctions virtuelles - Index

Les fonctions dynamiques sont autorisées pour les classes dérivées de System.TObject. Les fonctions dynamiques sont similaires aux fonctions virtuelles, sauf dans leur stockage dans les tables virtuelles.

  • Les fonctions virtuelles occupent un emplacement dans la table virtuelle de l'objet dans lequel elles sont définies, et dans la table virtuelle de chaque descendant de cet objet.
  • Les fonctions dynamiques occupent un emplacement dans chaque objet qui les définit, pas dans les descendants.

En d'autres termes, les fonctions dynamiques sont des fonctions virtuelles stockées dans des tables virtuelles éparses. Si vous appelez une fonction dynamique qui n'est pas définie dans votre objet, les tables virtuelles de ses ancêtres sont parcourues jusqu'à ce que la fonction soit trouvée.

En conséquence, les fonctions dynamiques réduisent la taille de vos tables virtuelles au prix d'un délai à l'exécution correspondant à la recherche de l'adresse des fonctions.

Comme les fonctions dynamiques sont disponibles seulement dans les classes dérivées à partir de TObject, vous obtenez une erreur si vous les utilisez dans une classe normale. Par exemple :

class dynfunc {
  int __declspec(dynamic) bar() { return 5; }
 };

donne l'erreur de syntaxe, "Erreur : La classe de stockage 'dynamic' n'est pas autorisée ici."

Mais le code suivant se compile :

#include <System.hpp>
#include <stdio.h>
class __declspec(delphiclass) func1 : public TObject {
 public:
  func1() {}
  int virtual virtbar() { return 5; }
  int __declspec(dynamic) dynbar() { return 5; }
 };
class __declspec(delphiclass) func2 : public func1 {
 public:
  func2() {}
  };
class __declspec(delphiclass) func3 : public func2 {
 public:
  func3() {}
  int virtbar() { return 10; }
  int __declspec(dynamic) dynbar() { return 10; }
 };
int main()
 { 
  func3 * Func3 = new func3; func1 * Func1 = Func3; 
  printf("func3->dynbar: %d\n", Func3->dynbar()); 
  printf("func3->virtbar: %d\n", Func3->virtbar()); 
  printf("func1->dynbar: %d\n", Func1->dynbar()); 
  printf("func1->virtbar: %d\n", Func1->virtbar()); 
  delete Func3; func2 * Func2 = new func2; 
  printf("func2->dynbar: %d\n", Func2->dynbar()); 
  printf("func2->virtbar: %d\n", Func2->virtbar()); 
  delete Func2; return 0; 
 }

L'attribut dynamic est hérité

En général, les fonctions dynamiques sont comme les fonctions virtuelles, et l'attribut dynamic est automatiquement hérité.

Toutefois, si un type dérivé déclare une méthode avec la même signature qu'une méthode dynamique dans un type de base, la méthode sera assignée au même identificateur dynamique, mais la méthode du type dérivé doit spécifier __declspec(dynamic). Sinon, le compilateur génère l'erreur : [Erreur BCC32] wibwob2.cpp(21) : E2113 Conflits de la fonction virtuelle 'func3::dynbar()' avec la classe de base 'func1'

Vous pouvez vérifier cela en exécutant l'exemple ci-dessus. Quand vous générez une sortie assembleur avec "bcc32 -S", vous pouvez examiner les tables virtuelles de func1, func2 et func3, et constater que func2 n'a pas d'entrée pour dynbar, mais qu'elle en a une pour virtbar. Vous pouvez toujours appeler dynbar dans l'objet func2 :

Sortie :

func3->dynbar: 10
func3->virtbar: 10
func1->dynbar: 10
func1->virtbar: 10
func2->dynbar: 5
func2->virtbar: 5

Les fonctions dynamiques ne peuvent pas devenir virtuelles (et vice-versa)

Vous ne pouvez pas redéclarer une fonction virtuelle en dynamique, de même que vous ne pouvez pas redéclarer une fonction dynamique en virtuelle. L'exemple suivant donne des erreurs :

 #include <vcl.h>;
 #include <stdio.h>;
 class __declspec(delphiclass) foo1 : public TObject {
  public:
   foo1() {}
   int virtual virtbar() { return 5; }
   int __declspec(dynamic) dynbar() { return 5; }
  };

 class __declspec(delphiclass) foo2 : public foo1 {
  public:
   foo2() {}
   int __declspec(dynamic) virtbar() { return 10; }
   int virtual dynbar() { return 10; }
  };

 Error : Cannot override a virtual with a dynamic function

 Error : Cannot override a dynamic with a virtual function

Voir aussi