Curso de C++ v2.0
Consultas, lista de correo 'C++ Con Clase' 'C++ Con Clase' página de entrada Librerías estándar C Tabla de contenido Contactar con Webmaster
*Introducción
*1 Toma de contacto
*2 Variables I
*3 Funciones I: Declaración y definición
*4 Operadores I
*5 Sentencias
*6 Declaración de variables
*7 Normas para la notación
*8 Cadenas de caracteres
*9 Conversión de tipos
*10 Variables II: Arrays
*11 Variables III: Estructuras
*12 Variables IV: Punteros 1
*13 Operadores II: Más operadores
*14 Operadores III: Precedencia
*15 Funciones II: Parámetros por valor y referencia
*16 Variables V: Uniones
*17 Variables VI: Punteros 2
*18 Operadores IV: De bits y condicional
*19 Definición de tipos
*20 Funciones III
*21 Funciones IV: Sobrecarga
*22 Operadores V: Sobrecarga
*23 El preprocesador
*24 Funciones V: Recursividad
*25 Variables VII: Modificadores
*26 Espacios con nombre
*27 Clases I: Definiciones
*28 Declaración de clases
*29 Constructores
*30 Destructores
*31 El puntero this
*32 Sistema de protección
*33 Modificadores para miembros
*34 Más sobre funciones
*35 Operadores sobrecargados
*36 Herencia
*37 Funciones virtuales
*38 Derivación múltiple
*39 Trabajar con ficheros
*40 Plantillas
*41 Punteros a miembros
 . Asignación
 . Operadores .* y ->*
*42 Castings
*43 Excepciones
*Ejemplos capítulos 1 a 6
*Ejemplos capítulos 8 y 9
*A Palabras reservadas C/C++
*B Trigrafos y símbolos alternativos
*C Librerías estándar
*D Streams
<< < > >>

41 Punteros a miembros de clases o estructuras

C++ permite declarar punteros a miembros de clases, estructuras y uniones. Aunque en el caso de las clases, los miembros deben ser públicos para que pueda accederse a ellos.

La sintaxis para la declaración de un puntero a un miembro es la siguiente:

<tipo> <clase|estructura|unión>::*<identificador>;

De este modo se declara un puntero "identificador" a un miembro de tipo "tipo" de la clase, estructura o unión especificada.

Ejemplos:

struct punto3D {
   int x;
   int y;
   int z;
};

class registro {
  public:
   registro();
   
   float v;
   float w;
};

int punto3D::coordenada; // (1)
float registro::valor;   // (2)

El primer ejemplo declara un puntero "coordenada" a un miembro de tipo "int" de la estructura "punto3D". El segundo declara un puntero "valor" a un miembro público de la clase "registro".

Asignación de valores a punteros a miembro:  

Una vez declarado un puntero, debemos asignarle la dirección de un miembro del tipo adecuado de la clase, estructura o unión. Podremos asignarle la dirección de cualquiera de los miembros del tipo adecuado. La sintaxis es:

<identificador> = &<clase|estructura|unión>::<campo>;

En el ejemplo anterior, serían válidas las siguientes asignaciones:

coordenada = &punto3D::x;
coordenada = &punto3D::y;
coordenada = &punto3D::z;
valor = &registro::v;
valor = &registro::w;

Operadores .* y ->*:  

Ahora bien, ya sabemos cómo declarar punteros a miembros, pero no cómo trabajar con ellos.

C++ dispone de dos operadores para trabajar con punteros a miembros: .* y ->*. A lo mejor los echabas de menos :-).

Se trata de dos variantes del mismo operador, uno para objetos y otro para punteros:

<objeto>.*<puntero>
<puntero_a_objeto>->*<puntero>

La primera forma se usa cuando tratamos de acceder a un miembro de un objeto.

La segunda cuando lo hacemos a través de un puntero a un objeto.

Veamos un ejemplo completo:

#include <iostream>
using namespace std;

class clase {
  public:
   clase(int a, int b) : x(a), y(b) {}
   
  public:
   int x;
   int y;
};

int main() {
   clase uno(6,10);
   clase *dos = new clase(88,99);
   int clase::*puntero;
     
   puntero = &clase::x;
   cout << uno.*puntero << endl;
   cout << dos->*puntero << endl;

   puntero = &clase::y;
   cout << uno.*puntero << endl;
   cout << dos->*puntero << endl;
   
   delete dos;
   cin.get();
   return 0;
}

La utilidad práctica no es probable que se presente frecuentemente, y casi nunca con clases, ya que no es corriente declarar miembros públicos. Sin embargo nos ofrece algunas posibilidades interesantes a la hora de recorrer miembros concretos de arrays de estructuras, aplicando la misma función o expresión a cada uno.

También debemos recordar que es posible declarar punteros a funciones, y las funciones miembros de clases no son una excepción. En ese caso sí es corriente que existan funciones públicas.

#include <iostream>
using namespace std;

class clase {
  public:
   clase(int a, int b) : x(a), y(b) {}
   int funcion(int a) { 
      if(0 == a) return x; else return y; 
   }
   
  private:
   int x;
   int y;
};

int main() {
   clase uno(6,10);
   clase *dos = new clase(88,99);
   int (clase::*pfun)(int);
   
   pfun = &clase::funcion;
   
   cout << (uno.*pfun)(0) << endl;
   cout << (uno.*pfun)(1) << endl;
   cout << (dos->*pfun)(0) << endl;
   cout << (dos->*pfun)(1) << endl;
 
   delete dos;
   cin.get();
   return 0;
}

Para ejecutar una función desde un puntero a miembro hay que usar los paréntesis, ya que el operador de llamada a función "()" tiene mayor prioridad que los operadores ".*" y "->*".

<< < > >>
Free Web Hosting