¡Nuevo!  por fin disponible la versión 5 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.9.16  Operadores añadidos a expresión

§1  Sinopsis

En este apartado se relacionan los operadores que aparecen a la derecha de una expresión; se incluyen en este grupo:

Operador de elemento de matriz [ ]  .

Operador de invocación de función ( )  .

Selector directo de miembro . de clases, estructuras y uniones  .

Selector indirecto de miembro -> de clases, estructuras y uniones  .

§2  Observaciones

( )     Utilizado para agrupar expresiones o delimitar expresiones condicionales.

        También indica llamadas de funciones y sus parámetros.

        Sirve también para definir las funciónes-objeto ( 5.1.3a1).

{ }     Principio y fin de sentencias compuestas.

[ ]     Señala subíndices de matrices simples y multdimensionales

.       Operador de acceso a miembros de clases, estructuras y uniones

->    Acceso a miembros de clases, estructuras y uniones.


§3  Operador de elemento de matriz [ ]

Este operador también es denominado subíndice o selector de miembro de matriz, ya que los corchetes [ ] sirven para señalar subíndices de matrices simples y multidimensionales.

Es un operador binario (de dos operandos)  m[n]. Cuando se utiliza con matrices de tipos simples (preconstruidos en el lenguaje) m es el identificador de la matriz y el índice n debe ser un entero positivo ( 4.3.1). Cuando se utiliza sobre tipos abstractos (instancias de clases), m es el identificador de una instancia de una clase M, y n puede ser cualquier valor (dependiendo de la definición dada por el programador). Pero entonces la expresión m[n] es equivalente a:

m.operator[](n);

donde operator[ ] es una función miembro no estática de M. Su definición puede ser cualquiera, pero generalmente devuelve una referencia a la clase M y acepta un int como argumento:

M::operator[] (int n) { /* ... */ }

La utilización de este operador con tipos abstractos supone que puede ser sobrecargado para operar con tipos definidos por el usuario ( 4.9.18d).


§3.1
  En el caso de matrices de tipos simples, la expresión:

<exp1>[exp2]

se define como:  *((exp1) + (exp2)), donde exp1 es un puntero y exp2 es un entero, o exp1 es un entero y exp2 es un puntero.

Ejemplo: la expresión arrX[3] se define como: *(arrX + 3), donde arrX es un puntero al primer elemento de la matriz; arrX + 3 es un puntero al cuarto elemento, y su indirección *(arrX + 3), es el valor del cuarto elemento de la matriz.


§3.2  En el caso de una matriz de tres dimensiones:  m[2][4][3]:

m[2][4][3]  ==    <m[2][4]> [3]  == *( ( m[2][4] ) + 3 )

m[2][4]  ==  <m[2]> [4]  == *( m[2] + 4 )  m[2][4][3] ==   *( *( m[2] + 4 ) + 3 )

m[2]   ==  *( m + 2 )                                                                      m[2][4][3] == *( *( *( m + 2 ) + 4 ) + 3 )

De forma general se tienen las siguientes relaciones:

Matriz de una dimensión:    m[a]  ==  *( m + a )

Matriz de 2 dimensiones:    m[a][b]  ==  *( *( m + a ) + b )

Matriz de 3 dimensiones:    m[a][b][c]  ==  *( *( *( m + a ) + b ) + c )

Matriz de 4 dimensiones:    m[a][b][c][d]  ==  *( *( *( *( m + a ) + b ) + c )+ d)

etc.


§4  Operador de llamada a función  ( )

En C++ una invocación del tipo  func(lista-de-argumentos) es considerada como un operador binario ( 4.9); el denominado operador de invocación a función ( ), que se aplica entre el primer argumento func y el segundo, lista-de-argumentos. En este sentido, la invocación anterior sería equivalente a: func()lista-de-argumentos, aunque en realidad, la sintaxis utilizada sea la primera.

§4.1  Sintaxis

postfix-expression(<arg-expression-list>)

§4.2  Ejemplo

x = somefunc(x, 33, z);     // el valor se asigna a x

§4.3  Comentario

El valor (si lo tiene) de la llamada a función es el valor devuelto por esta, tal como se establece en la definición de la función.

Recordar que el paréntesis ( ) puede ser también un elemento de puntuación para agrupar expresiones aritméticas; para aislar expresiones condicionales y para delimitar expresiones con coma.

Este operador puede ser sobrecargado mediante la función-operador operator( ) ( 4.9.18f).

§5  Selector directo de miembro

El selector directo de miembro ( . ) es un operador binario que debe usarse para acceder a los miembros de clases, estructuras y uniones.

§5.1  Sintaxis

expresión . identificador

  expresión debe ser un objeto de tipo clase, unión o estructura.

  identificador debe ser un miembro de la clase, unión o estructura indicada en expresión.

§5.2  Ejemplo

class CLASE {

   int i;  

   public:

   double d;

   int geti() { return i; }

} c1 ;

 ...

c1.d = 3.14;         // asigna 3.14 al miembro d del objeto c1

int z = c1.geti();   // invoca el método geti del objeto c1

§5.3  Comentario

Suponiendo que el objeto s sea una instancia de la estructura tipo S. Entonces, si m es el identificador de un miembro de tipo M declarado en S, la expresión s.m es de tipo M y representa al sub-objeto m en s.

Ejemplo:

struct S {...; M m; ...; };  // m es miembro de S tipo M
S s;            // s es instancia de S
M x = z;
s.m = x;        // asigna x al miembro m de s


Una expresión del tipo  sT.obj representa el objeto obj de la estructura sT. (la expresión es un Lvalue siempre que sT no lo sea y obj no sea una matriz).

Si existen clases o estructuras anidadas, es decir, si una estructura SB contiene un campo que es a su vez una estructura SA, los miembros de la estructura anidada SA pueden ser accedidos mediante una doble aplicación del selector directo de miembro. Ejemplo:

struct SA { int i; char ch; } a;

struct SB { int i; char ch; struct a; } b;

 ...

b.i = 3;       // asigna 3 al miembro i del objeto b

b.ch = 'a';    // asigna 'a' al miembro ch del objeto b

b.a.i = 3;     // asigna 3 al miembro i del sub-objeto a de b

b.a.ch = 'a';  // asigna 'a' al miembro ch del sub-objeto a de b


§6  Selector indirecto de miembro

El selector indirecto de miembro ( -> ) es un operador binario que puede utilizarse para acceder a miembros de clases, estructuras y uniones a través de punteros.

Nota: el hecho de acceder a objetos a través de punteros se denomina indirección (de ahí el nombre de este operador), y constituye un recurso de capital importancia y constante uso en programación (comentarios adicionales en 4.9.11).

§6.1  Sintaxis

ClPtr -> identificador

  ClPtr debe ser un puntero a clase; puntero a estructura o puntero a unión.

  identificador debe ser el nombre de un miembro de la clase, estructura o unión a que señala el puntero.

§6.2  Ejemplo

class CLASE {

   public:

   double db;

   double getd() { return db; }

} c1, *cptr = &c1;

  ...

cptr->db = 1.23;       // asigna 1.23 al miembro db de c1      §6.2a

cptr->getd();          // invoca método getd del objeto c1     §6.2b

cptr->CLASE::getd();   // variación sintáctica de la anterior  §6.2c

§6.3  Comentario

Si existen clases o estructuras anidadas, es decir, si la estructura B contiene un campo a de tipo estructura A, los sub-miembros de a pueden ser accedidos mediante una doble aplicación del operador de selección.

Ejemplo:

struct A {

   int j;  double x;

};

struct B {

   int i;  double d;

   struct A a;

} s, *sptr = &s;

    ...

sptr->d = 1.2;      // asigna 1.2 al miembro d de B

s.d = 1.2;          // ídem.

sptr->a.x = 3.1;    // asigna 3.1 al miembro x de A

s.a.x = 3.1;        // ídem.

Una expresión del tipo ClPtr -> memb representa el miembro memb de la clase Cl siempre que ClPtr sea un puntero a dicha clase (la expresión es un Lvalue siempre que memb no sea una matriz). Esta expresión es equivalente, y preferible a (*clPt).memb

Observe que las expresiones §6.2a, §6.2b y §6.2c pueden ser sustituidas con éxito por la combinación de otros operadores disponibles en el lenguaje, de forma que son equivalentes a:

(*cptr).db = 1.23;
(*cptr).getd();
(*cptr).CLASE::getd();

En realidad la introducción de un operador específico para estos menesteres se debe a que la indirección, a la que nos hemos referido antes, es un elemento clave en programación, importancia que queda subrayada en C++ por la dedicación de este operador específico que simplifica y resalta el mecanismo de acceso cuando se trata de punteros a clases, estructuras y uniones. En estos casos, la notación

cptr->db = 1.23;

es más elegante y concisa que su contrapartida

(*cptr).db = 1.23;

Además, como tendremos ocasión de ver al tratar de la sobrecarga de este operador ( 4.9.18e) la indirección dar lugar a técnicas de programación muy interesantes (a este respecto puede verse también un ejemplo en 4.9.18c).

  Este operador puede ser sobrecargado mediante la función-operador operator-> ( 4.9.18e).