Disponible la versión 6 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]


5.2.2  Localismos

§1 Localismos C++

Hemos señalado ( 5.2) que la clase locale tiene un doble carácter: es al mismo tiempo una interfaz y un índice o clasificador de un conjunto de clases (facet), cada una de las cuales encapsula un aspecto concreto de la localización. En la página adjunta ( 5.2.3) se incluye la interfaz de esta clase cuyas características principales pasamos a comentar (su descripción detallada puede encontrarla en el manual de su compilador).

§2  Nombre

Los objetos de la clase pueden tener un nombre o ser anónimos. Solo los objetos creados desde un nombre (ver ); desde dos locales con nombre, o desde un flujo, tienen nombre. Su valor puede obtenerse mediante un método público constante preparado al efecto:

basic_string<char> name() const;

La función name() devuelve el nombre del locale (el nombre de *this), y el resultado de locale(name()) es equivalente a *this. Si es anónimo, name() devuelve la cadena "*" y el resultado de locale(name()) depende de la implementación.

Solos los locale con nombre pueden ser comparados para igualdad (utilizados como operandos del operador ==), los locale anónimos solo son iguales a sí mismos.

§3  Constructores

En la definición de la clase encontramos diversos tipos de constructores, incluyendo varios constructores-copia; un constructor por defecto y otro explícito:

locale() throw()                           // C1: constructor por defecto

locale(const locale& other) throw()        // C2: constructor-copia

explicit locale(const char* std_name);     // C3: constructor explícito

locale(const locale& other, const char* std_name, category cat);  // C4: template

<class Facet> locale(const locale& other, Facet* fac);            // C5:

locale(const locale& other, const locale& one, category cat);     // C6:

§3.1  Constructor por defecto 

El constructor por defecto locale() crea una copia del localismo global actual, que actúa como localismo por defecto. Es decir, construye una copia del objeto utilizado como argumento en la última invocación al método global (). Si este método no hubiera sido utilizado, entonces el localismo por defecto del programa es el ANSI "C", y el resultado obtenido es idéntico al de utilizar el método classic ().

Nota:  Este constructor es utilizado frecuentemente como argumento por defecto para los métodos que reciben un argumento de tipo const locale&.  Por ejemplo, combine() y global().

§3.2  Constructor-copia C2

El constructor-copia C2 permite crear un objeto local que es copia de otro (other) utilizado como argumento.

§3.3  Constructor explícito C3

El constructor explícito

explicit locale(const char* std_name);

permite crear un objeto local a partir de una representación externa, identificada por una cadena de caracteres, representada a su vez por el puntero std_name.  La cadena puede ser cualquiera de las utilizadas con la función setlocale() de C ( 5.2.4). En caso que el identificador std_name no sea válido, lanza una excepción runtime_error ( 1.6.1a).  Ejemplo:

float fl = 1.2345F;

std::cout << fl << std::endl;    // 1.2345

std::locale L1("german");

std::cout.imbue(L1);

std::cout << fl << std::endl;    // 1,2345

Nota:  Observe que este constructor y el siguiente (parcialmente) son los únicos que permiten incorporar al interior del programa las especificaciones locales contenidas en ficheros externos (definidos por el argumento std_name)

§3.4  Constructor C4

El constructor

locale(const locale& other, const char* std_name, category cat);

construye un objeto local que es copia del especificado en el argumento other.  A excepción de las facetas comprendidas en la categoría indicada en el argumento cat, que serán sustituidas por las obtenidas del modelo identificado por std_name  (ver el punto anterior). En caso que std_name sea un argumento inválido o nulo, se genera una excepción runtime_error.

El objeto resultante tiene un nombre solo si el modelo other lo tiene.

§3.5  Constructor C5

El constructor

template <class Facet> locale(const locale& other, Facet* fac);

construye un objeto que es copia del señalado en el argumento other.  Incorpora todas sus facetas, a excepción del tipo señalado por Facet.  La faceta faltante se sustituye por la señalada en este argumento. Si fac es un puntero nulo, el objeto obtenido es una réplica exacta del modelo other.  En cualquier caso, el objeto resultante no tiene nombre.

§3.6  Constructor-copia C6

El constructor

locale(const locale& other, const locale& one, category cat);

construye un objeto locale que es copia de other, excepto las facetas incluidas en la categoría category, que son obtenidas del objeto one.  El objeto resultante tiene nombre solo en caso que lo tengan los objetos other y one. Ejemplo:

locale loc ( locale::classic(), locale("De_DE"), LC_NUMERIC );

El objeto loc es una copia del entorno estándar ANSI "C" (ver a continuación), a excepción de las facetas numéricas que son copiadas del entorno Alemán "De_DE".

Nota:  Observe que la mayoría de constructores-copia están definidos en términos de referencias. En realidad estas copias son operaciones económicas (en términos de computación) porque los argumentos pasan por referencia ( 4.4.5).  Además cuando se copia un objeto solo se crea su manejador ("handle"), por lo que el paso de estos objetos como argumentos de funciones también es un proceso económico aunque el paso se realice por valor. Incluso la utilización del constructor por defecto (C1 ) es una operación económica porque en realidad se copia el locale global. Los constructores que aceptan un segundo objeto son ligeramente más costosos porque requieren clonar el cuerpo del objeto aunque quizás no sean copiadas todas sus facetas. El constructor C6 es el más costoso porque requiere crear un objeto local desde una representación externa (el argumento one).

§4  Otros métodos

La clase locale también se dispone de sendas funciones que sin ser propiamente constructores, pueden ser utilizados como tales. Son los métodos classic() y combine().

§4.1  El método classic()

Como puede verse, este método  devuelve una referencia a un objeto locale:

static const locale& classic();

En realidad devuelve una referencia a un objeto global que representa el equivalente C++ del entorno estándar "C" ( 5.2). Es el mismo resultado que podría obtenerse con la invocación del constructor explícito (C3 ):

locale("C");

§4.2  El método combine():

Responde al prototipo

template <class Facet> locale combine(const locale& other);

Es un método un tanto singular desde el punto de vista C++. Es una función genérica que sin ser un constructor (como C5 ), devuelve un objeto locale que es copia de *this ( 4.11.6), a excepción de las facetas de tipo Facet, que son tomadas del argumento other. Si el objeto other no contiene facetas del tipo Facet, se genera una excepción de tipo runtime_error.

El objeto obtenido no tiene nombre.

§4.3  Métodos públicos estáticos
§4.3.1  El método global()

Es un método estático público de prototipo

static locale global(const locale& loc);

Este método realiza una doble tarea: establece el locale global a un nuevo valor definido por el argumento loc, y devuelve el valor anterior. Recuerde que el locale global afecta al resultado obtenido en las invocaciones al constructor por defecto (C1), de forma que las sucesivas invocaciones a este constructor instanciarán copias de loc.

Si loc tiene nombre, la invocación a global() tiene el efecto adicional de producir la invocación:

std::setlocale(LC_ALL, loc.name().c_str());

En caso contrario el efecto en el locale C depende de la implementación

Nota:  Recordemos que la función c_str() es un método público de la clase basic_string ( xx) que responde a la siguiente declaración:

const charT* c_str() const;

Devuelve un puntero el elemento inicial de una matriz cuyo primer elemento es igual a la cadena controlada por *this.

La figura adjunta [1] muestra un esquema de la arquitectura de los localismos C++. Puede verse que un locale es en realidad el manejador de una entidad que mantiene un contenedor (vector ) de punteros a facetas.

Una propiedad fundamental de los objetos locales es su inmutabilidad. Una vez que se ha instanciado un objeto locale, no puede ser modificado. Esta característica se ha implementado con objeto de hacerlos seguros y fáciles de utilizar, pero hace que una vez creados, sea imposible sustituir alguna de sus facetas. Todo debe quedar definido en el momento de la construcción del objeto locale.

Nota:  El programador está acostumbrado a que cuando se utilizan punteros o referencias a los elementos de un contenedor, debe preocuparse de verificar su validez, ya que si el contenedor cambia, los punteros y referencias a sus miembros pueden dejar de ser válidos. En cierto sentido un locale es también un contenedor de facets, y el hecho que no pueda cambiar asegura que mientras dure la existencia del objeto o cualquiera de sus copias, puedan utilizarse referencias a sus miembros sin preocupación.

Otra interesante característica de los locales es la forma en que se acceden sus facetas. Esto no se realiza mediante un método de la clase como cabría esperar, sino mediante un par de funciones externas que aceptan un locale como argumento. Es posible determinar si un objeto determinado contiene una faceta mediante la función has_facet ( 5.2.1). A su vez la función use_facet ( 5.2.1) devuelve una referencia a la facet para que pueda ser utilizada.

  Inicio.


[1] Del manual Borland "Standar C++ Library Help".