[Tutorial C++] II.1 - Estructura del programa C++

Ver el tema anterior Ver el tema siguiente Ir abajo

[Tutorial C++] II.1 - Estructura del programa C++

Mensaje  HarZe el Vie Jul 02, 2010 5:29 pm

La estructura de un programa en C++ es totalmente libre. Solo debes cumplir las normas de ámbito, es decir, tener bien claro el ámbito de cada variable, de cada función, de cada objeto; pues eso es lo característico de C++, su flexibilidad. Por lo que me voy a centrar en como agrupar los datos, un ejemplo de código:

Código:
#include <iostream>

int pi = 3;

namespace mates {
    float radio = 5.0f;
    const float pi = 3.141592f;
    float longitud_circunferencia(float rad) {
        return (rad*pi*2);
    }
}

int main() {
    std::cout << "El valor de PI es: " << mates::pi << "\n";
    {
        using namespace std;
        cout << "El valor del radio es: " << mates::radio << "\n";
        using namespace mates;
        cout << "La longitud de la circunferencia es: " << longitud_circunferencia(radio) << "\n";
    }
    std::cout << "El valor de PI entero es: " << pi << "\n";
    using namespace std;
    cout << "El valor de PI es: " << mates::pi << "\n";
    using namespace mates;
    //cout << "El valor de PI es: " << pi << "\n";
    return 0;
}

Hay muchos niveles de ámbitos. Los ámbitos de funciones (variables públicas o privadas) se tratarán más adelante, al igual que los componentes internos o externos de los objetos (clases). Los ámbitos que aquí voy a tratar son: global, espacio de nombre y llaves.

Las variables globales son aquellas declaradas al inicio, fuera de cualquier función; aunque si es dentro de main(), ya que ésta es la primera función, también se considera una variable global. Esto quiere decir que desde cualquier punto del programa se puede acceder a ella y tiene el ámbito máximo, es decir, todo el programa.
Ejemplos en el código serían:
Código:
float radio = 5.0f;
int pi = 3;

El siguiente nivel de ámbito es artificial, y puede englobar variables, funciones e incluso objetos (clases). Dado que venimos de C, omitiré objetos por ahora. Así funcionaría los "espacios de nombre": namespace.
Código:
namespace nombre {
    declaracion de variables
    declaracion de funciones
    declaracion de objetos
}
Y para poder usar luego esas variables, funciones u objetos, hay que usar el operador enlace (::) es decir, una vez definida, para usar una sería:
Código:
namespace nombre {
    int variable;
}
....
nombre::variable = 5;
Pero en el caso de que vayamos a usar mucho el contenido de un namespace, es mejor poner:
Código:
using namespace nombre;
variable = 5;
Es decir, a través de using podemos decir que se "use" ese namespace por defecto, ahorrándonos usar el operador enlace cada vez.

El código está plagado de ejemplos, pero antes de explicarlo, diré una cosa más: los bloques. Un bloque es simplemente un código cerrado por llaves, y todo aquello que se declare dentro, no podrá ser usado fuera.

Ahora voy a explicar el código:
std::cout << "El valor de PI es: " << mates::pi << "\n"; Ordena imprimir en pantalla la variable pi que esta en el namespace mates. La propia orden necesita un std:: porque tanto cout como cin están declarados en el namespace std.
Código:
    {
        using namespace std;
        cout << "El valor del radio es: " << mates::radio << "\n";
        using namespace mates;
        cout << "La longitud de la circunferencia es: " << longitud_circunferencia(radio) << "\n";
    }
Este es un bloque entero, una vez acabe, todo aquello que hayamos creado dentro quedará destruido. Empieza con using namespace std;, que permite usar cout de forma sencilla, pero sólo dentro del bloque, una vez fuera el using se anula, como ya veremos. Después cout << "El valor del radio es: " << mates::radio << "\n"; imprime el radio, el cual necesita mates:: porque pertenece a ese namespace. Con using namespace mates; evitamos poner el prefijo mates::, y en cout << "La longitud de la circunferencia es: " << longitud_circunferencia(radio) << "\n"; no tenemos que poner el prefijo ni a radio ni a la función que calcula la longitud de la circunferencia con ese radio. Pero el bloque se cierra, y desde ahora, será como si los using nunca hubiesen existido.
std::cout << "El valor de PI entero es: " << pi << "\n"; Es la prueba de lo dicho antes, ha habido que poner std:: de nuevo. Imprime el valor pi, pero ya no es el valor real de PI que contiene mates::pi, es su valor entero: 3. Otra prueba más de que no detecta la variable pi del namespace, sino la global.
Código:
    using namespace std;
    cout << "El valor de PI es: " << mates::pi << "\n";
Ahora podemos usar de nuevo cout simplificado, pero aun tenemos que indicar de que pi estamos hablando.
Código:
    using namespace mates;
    //cout << "El valor de PI es: " << pi << "\n";
Esto es lo más interesante, y es a donde quería llegar. Es donde se ve el principal problema de using. Pero primero veamos a que me refiero. Tenemos a pi (variable global, tipo int, de valor 3) y a pi (realmente es mates::pi, pero con using omitimos mates::, contiene el valor decimal de PI), es decir, dos variables distintas con un mismo nombre para el compilador. Y en la línea siguiente (que es un comentario para que no se ejecute, pues daría error, compruébalo quitando las dos barras) se pide que imprima pi, ¿pero qué pi imprime? Pues ninguno, da error. Realmente no es un error de C++, es un error del compilador, que es quien permite usar using como un "atajo" del estilo de typedef y #define en C.
Conclusión: tienes dos opciones. Nunca usar using y usar siempre el operador de enlace (::), que nunca dará errores. Jugártela y usar using, que es más cómodo, al precio de posibles errores.

HarZe
WebMaster & Desarrollador

Cantidad de envíos : 58
Fecha de inscripción : 21/06/2009
Edad : 24

Ver perfil de usuario http://opengl-esp.superforo.net

Volver arriba Ir abajo

Ver el tema anterior Ver el tema siguiente Volver arriba

- Temas similares

 
Permisos de este foro:
No puedes responder a temas en este foro.