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.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).