Disponible la nueva versión "donationware" 7.3 de OrganiZATOR
Descubre un nuevo concepto en el manejo de la información.
La mejor ayuda para sobrevivir en la moderna jungla de datos la tienes aquí.

Curso C++

[Home]  [Inicio]  [Índice]


4.11.8b   Funciones dinámicas

§1  Antecedentes

Las funciones dinámicas son una particularidad del compilador C++Builder, y están relacionadas con las clases VCL, otra peculiaridad de este compilador.

Nota: como tales peculiaridades no se corresponden con el Estándar ANSI C++. Estas y en general, todas las características que no estén bien definidas o sean particularidades de algún fabricante es preferible obviarlas. En especial si la portabilidad del código es un factor a tener en cuenta. Presentan además el peligro añadido que el fabricante decida discontinuarlas en futuras versiones del compilador.


§2  Las clases VCL (Visual Component Library), son colecciones de objetos en Pascal. Se trata de una serie de recursos pre-construidos de los que puede echar mano el programador para integrarlos en sus aplicaciones. Constituyen una parte muy importante del IDE (Integrated Development Environment) de C++Builder, que como indica su nombre, es un Entorno Integrado de Desarrollo (eminentemente visual) con el que se pueden diseñar, compilar y depurar aplicaciones C++ con una mínima escritura manual de código. Es similar a la STL (Standard Template Library) de C++ [1]; a la MFC (Microsoft Foundation Classes) de MicroSoft [2]; a la AWT de Java, etc.

Nota: este principio de utilización de elementos preconstruidos ha estado presente desde siempre en la programación (es la esencia de una función o subrutina), aunque actualmente alcanza proporciones e importancia nunca vistas. Es el principio de un nuevo paradigma de programación, en especial de la informática distribuida, donde el asunto deriva hacia una serie de objetos que se interrogan mutuamente y se intercambian información, no importa en que soporte físico, donde estén ubicados, ni en que lenguaje están escritos. Los modernos IDE representan sin duda un gran avance, aunque a los viejos programadores nos de un poco de vértigo la pérdida de contacto con el código que subyace en estas herramientas visuales.


Borland C++ utiliza esta misma terminología VCL para una parte de su librería de objetos. De hecho, la VCL de BC++ se desarrolló inicialmente en Pascal, posteriormente se utilizó para Delphi (este compilador ha sido durante mucho tiempo el buque insignia de esta empresa de software), y está construida (1999) en Object Pascal (otro compilador importante de dicha empresa). En consecuencia es también el resultado de un "principio de reutilización de recursos" por parte de este fabricante de software.

Según indica al respecto la propia ayuda de C++Builder, la Librería de Componentes Visuales (VCL) utiliza un modelo PME (basado en propiedades, métodos y eventos). Este modelo define las propiedades; los métodos para operar con ellas, y un medio para interactuar con los usuarios de la clase (los eventos). La librería VCL está construida como una jerarquía de objetos escritos en Object Pascal y ligados al IDE de C++Builder, que permite el desarrollo rápido de aplicaciones.

El IDE de C++Builder espera que el nombre de cada clase VCL comience por la letra “T”. Por tanto, dicha T es ignorada siempre cuando se le asigna identificación por el compilador. Por ejemplo, una declaración class Test origina un identificador en el programa sin la T inicial.

§3  Sinopsis

Las funciones dinámicas son similares a las funciones virtuales ( 4.11.8a) excepto en la forma en que alojan sus direcciones en la tabla virtual. Mientras que las funciones virtuales ocupan un espacio en la tabla virtual de la clase en que son definidas y en la de cada subclase descendiente, las funciones dinámicas en cambio, ocupan un espacio en la tabla de cada clase que las define, pero no en las subclases descendientes. Es decir, las funciones virtuales son como las dinámicas pero utilizan tablas más reducidas.

Como consecuencia de lo anterior, cuando se invoca una función dinámica y esta función no está definida en la clase de la que se instancia el objeto, se recorre hacia arriba la jerarquía de clases hasta que se encuentra la definición en la tabla de alguna de ellas.

La segunda consecuencia inmediata es que el tamaño de las tablas virtuales se reduce en perjuicio de la eficacia de ejecución, ya que este recorrido retrospectivo de la jerarquía de clases en búsqueda de las direcciones de las funciones consume su tiempo.

§4  Sintaxis:

La declaración de una función como dinámica exige una sintaxis especial con la utilización del declarador __declspec(dynamyc):

<tipo-devuelto> __declspec(dynamic) nombre-funcion (<tipo> <parametro>, ... )

§5  Comentario

Las funciones dinámicas se permiten solo en clases que deriven de una clase especial denominada TObject. Por esta razón se genera un error cuando se utilizan en una clase normal. Por ejemplo, las sentencias:

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

produce un error de compilación: “Error: Storage class 'dynamic' is not allowed here”. Sin embargo, el código que sigue es correcto:

#include <vcl.h>
#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 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;
}

Salida:

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

§5.1  El atributo dinámico es heredable

Lo mismo que en las funciones virtuales, el atributo dinamic también es heredado automáticamente por las subclases, lo que puede ser comprobado ejecutando el ejemplo anterior. Cuando se genera una salida en ensamblador mediante el comando -S del compilador C++Borland ("bcc32 -S") pueden examinarse las tablas virtuales de las clases func1, func2, y func3, donde puede comprobarse como func2 no tiene entrada para la función dinámica dynbar, pero si para virtbar. A pesar de lo cual, puede invocarse dynbar en el objeto instanciado de la clase func2.

§5.2  Las funciones dinámicas no pueden ser virtuales y viceversa

No está permitido redefinir una función virtual para que sea dinámica; así mismo, tampoco puede redefinirse una función dinámica para que sea virtual. El ejemplo que sigue produce errores:

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

Resultado de la compilación

Error:  Cannot override a virtual with a dynamic function
Error:  Cannot override a dynamic with a virtual function


  Inicio.


[1]  STL (Standard Template Library).  Este es el nombre que recibe un gran conjunto de estructuras de datos y algoritmos que conforman una parte importante de la Librería Estándar de C++ ( 5).

[2]  La MFC (Microsoft Foundation Classes) es la librería de clases C++ para programación en el entorno Windows. Está incluida en el compilador Microsoft Visual C++.