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]


Operador de indirección: ejemplo


El programa muestra un esquema de la casuística de acceso a instancias de clase y a miembros utilizando el operador de indirección * estándar, así como los operadores específicos .* y ->* ofrecidos por C++ para estos casos.

El ejemplo define una clase C que tiene tres propiedades y un método. Tanto la propiedad x como el método fm son referenciados por sendos punteros: uno de ellos es miembro de la propia clase; el otro es exterior a ella. El cuerpo de main se limita a instanciar un objeto c1 de la clase y un puntero pc al objeto. A continuación se muestran diversos ejemplos de la sintaxis posible para acceder a la propiedad x del objeto, e invocar al método fm a través de sus punteros.

#include <iostream>
using namespace std;

class C {
  public:
  int x;
  void fm() {cout << "Funcion" << endl; }
  int C::* mpint;        // miembro puntero-a-int
  void (C::* mpfm)();    // miembro puntero-a-funcion miembro
  C (int n = 0) {        // constructor por defecto
    x = n;
    mpint = &C::x;
    mpfm = &C::fm;
  }
};

int (C::* pmint) = &C::x;    // puntero-a-miembro-int
void (C::* pfm)() = &C::fm;  // puntero-a-miembro-funcion


int main (void) {            // ========================
  C c1(10);                    // M.1: Instancia objeto c1
  C* pc = &c1;                 // define puntero al objeto
// acceso al miembro x
  cout << "1.a.- c1.x == " << c1.x           << endl;
  cout << "1.b.- c1.x == " << c1.*pmint      << endl;
  cout << "1.c.- c1.x == " << c1.*(c1.mpint) << endl;
  cout << "1.c1- c1.x == " << c1.*c1.mpint   << endl;        // Eq.
// sustitucion de c1 por su equivalente *pc
  cout << "2.a.- c1.x == " << (*pc).x              << endl;
  cout << "2.b.- c1.x == " << (*pc).*pmint         << endl;
  cout << "2.c.- c1.x == " << (*pc).*((*pc).mpint) << endl;
  cout << "2.c1- c1.x == " << (*pc).*(*pc).mpint   << endl;  // Eq.
// sustitucion de (*pc). por el su quivalente pc->
  cout << "3.a.- c1.x == " << pc->x                << endl;
  cout << "3.b.- c1.x == " << pc->*pmint           << endl;
  cout << "3.c.- c1.x == " << pc->*(pc->mpint)     << endl;
  cout << "3.c1- c1.x == " << pc->*pc->mpint       << endl;  // Eq.
// invocacion del metodo fm del objeto c1
  cout << "4.a.- Invocar c1.fm() == "; c1.fm();
  cout << "4.b.- Invocar c1.fm() == "; (c1.*pfm)();
  cout << "4.c.- Invocar c1.fm() == "; (c1.*(c1.mpfm))();
  cout << "4.c1- Invocar c1.fm() == "; (c1.*c1.mpfm)();      // Eq.
// sustitucion de c1 por su equivalente *pc
  cout << "5.a.- Invocar c1.fm() == "; (*pc).fm();
  cout << "5.b.- Invocar c1.fm() == "; ((*pc).*pfm)();
  cout << "5.c.- Invocar c1.fm() == "; ((*pc).*((*pc).mpfm))();
  cout << "5.c1- Invocar c1.fm() == "; ((*pc).*(*pc).mpfm)();
// sustitucion de (*pc). por el su quivalente pc->
  cout << "6.a.- Invocar c1.fm() == "; pc->fm();
  cout << "6.b.- Invocar c1.fm() == "; (pc->*pfm)();
  cout << "6.c.- Invocar c1.fm() == "; (pc->*(pc->mpfm))();
  cout << "6.c1- Invocar c1.fm() == "; (pc->*pc->mpfm)();
  return 0;
}

Salidas:  solo hay dos tipos (todas iguales):

x.y.- c1.x == 10
m.n.- Invocar c1.fm() == Funcion

Comentario

La precedencia de operadores ha permitido suprimir paréntesis en algunas sentencias. En estos casos se ha incluido la expresión simplificada equivalente debajo de la original con la indicación Eq (Equivalente).

Las sentencias se agrupan en seis bloques que forman dos grandes grupos: Los tres primeros muestran diversas formas de acceso a la propiedad x del objeto c1. Los tres últimos son formas de invocación del método fm. Dentro de cada grupo las sentencias con la misma letra guardan cierta relación entre si.

La salida 1.a del primer grupo, obtiene el valor del miembro x directamente, mediante la utilización del selector directo de miembro . ( 4.9.16). Las salidas 1.b y 1.c representan el acceso a x mediante los punteros externo e interno respectivamente (es digna de atención la sintaxis utilizada en las formas n.c de acceso a miembros mediante punteros internos).

El grupo de salidas 2 se ha obtenido del anterior sustituyendo el designador del objeto (c1) por su valor equivalente, que se obtiene mediante indirección de su puntero ( *pc ).

El grupo 3 se obtiene del anterior mediante sustitución de la expresión (*pc). por su sintaxis equivalente utilizando el selector indirecto -> ( 4.9.16d).

El proceso se repite de forma paralela con los grupos 4, 5 y 6, aunque en este caso, el acceso a fm sirve para invocar la ejecución de este método en la instancia c1.

Cuando el objeto c1 está disponible se utilizan las formas 1 y 4. Las restantes solo son útiles cuando el objeto c1 no es accesible directamente, sino a través de su puntero pc (por ejemplo cuando el objeto pasa como argumento a una función mediante un puntero). Las formas 2 y 5, aunque perfectamente válidas no son muy usuales. En su lugar se prefiere utilizar las formas equivalentes 3 y 6 (precisamente una de las razones para la introducción de este operador es, entre otras [1], simplificar la sintaxis).

  Inicio.


[1]  En realidad, el acceso a miembros está perfectamente atendido con la sintaxis existente, que aunque farragosa, no lo es más que el resto de la sintaxis C++. Otra razón para la introducción de un único operador capaz de manejar una expresión del tipo *pc. es permitir su sobrecarga ( 4.9.18e).