domingo, 20 de marzo de 2016

GET Y SET EN C++
Cuando tienes una clase, ya sea en java, c++... las clases tienen atributos, para poder asignarles valores o modificar esos atributos se usa el metodo set (establecer), y cuando quieres ver el contenido de estos mismos, se utiliza el metodo get (obtener) 

te voy a hacer un ejemplo para que te quede claro: 

//primero creamos una clase 

class persona{ 
private: 
int edad; //atributo entero para la edad 

public: 
//ahora creamos el set para establecer la edad 
//siempre debera ser tipo void, pues no devuelve nada 
void setedad(int edad); 

//ahora el get para obtener la edad, debe ser del tipo del atributo 
int getedad(); 

void mostraredad(); //metodo que usaremos para explicar 
}; 


//ahora escribimos el codigo de cada metodo 

//creamos el metodo set, para modificar atributo 
void persona::setedad(int edad); 
this->edad=edad;} 

//metodo get para que devuelva el atributo 
int persona::getedad(){ 
return this->edad;} 

void persona::mostraredad(){ 
int x; 
cout<<"ingrese la edad: "; 
cin>>x; 
this->setedad(x); //le asigna al atributo edad, el valor que //acabamos de ingresar 
cout<<"la edad de la persona es: "; 
cout<<this->getedad();//imprime el valor del atributo edad 


//luego creas un objeto en el main y llamas al metodo, 

void main(){ 
persona*p=new persona(); 
p->mostraredad(); 



espero que te haya quedado claro, cualquier consulta me contactas!! 
POLIMORFISMO
En lenguajes basados en clases y con un sistema de tipos de datos fuerte (independientemente de si la verificación se realiza en tiempo de compilación o de ejecución), es posible que el único modo de poder utilizar objetos de manera polimórfica sea que compartan una raíz común, es decir, una jerarquía de clases, ya que esto proporciona la compatibilidad de tipos de datos necesaria para que sea posible utilizar una misma variable de referencia (que podrá apuntar a objetos de diversas subclases de dicha jerarquía) para enviar el mismo mensaje (o un grupo de mensajes) al grupo de objetos que se tratan de manera polimórfica.
No obstante, algunos lenguajes de programación (Java, C++) permiten que dos objetos de distintas jerarquías de clases respondan a los mismos mensajes, a través de las denominadas interfaces (esta técnica se conoce como composición de objetos). Dos objetos que implementen la misma interfaz podrán ser tratados de forma idéntica, como un mismo tipo de objeto, el tipo definido por la interfaz. Así, distintos objetos podrán intercambiarse en tiempo de ejecución –siempre que sean del mismo tipo–, y además con dependencias mínimas entre ellos. Por estos motivos se considera un buen principio de diseño en programación orientada a objetos el favorecer la composición de objetos frente a la herencia de clases.1
En Java las interfaces se declaran mediante la palabra clave Interface. Estas se utilizan para lograr la necesaria concordancia de tipos que hace posible el polimorfismo, también como un contrato que debe cumplir cualquier clase que implemente una cierta interfaz, y como una forma de documentación para los desarrolladores. A veces, en la literatura específica sobre Java se habla de "herencia y polimorfismo de interfaces", lo que no concuerda con los conceptos de la programación orientada a objetos porque una clase que implementa una interfaz sólo obtiene su tipo de datos y la obligación de implementar sus métodos, no copia comportamiento ni atributos. Esta terminología puede llevar a confusión, puesto que en Java a menudo se utiliza la mal llamada "herencia de interfaces" para dotar a una clase de uno o varios tipos adicionales, lo que unido a la composición, evite la necesidad de la herencia múltiple y favorezca una utilización más amplia del polimorfismo.
No obstante, el uso de una jerarquía de clases como paso previo, es muy habitual incluso en aquellos lenguajes en los que es posible prescindir de tal jerarquía, ya que, desde una perspectiva conceptual, se puede decir que al pertenecer los "objetos polimórficos" a subclases de una misma jerarquía, se asegura la equivalencia semántica de los mensajes que se invocarán de modo polimórfico. Por esto, en programación orientada a objetos a veces se denomina al polimorfismo como "polimorfismo de subclase (o de subtipo)".
En resumen, en la programación orientada a objetos, la esencia del polimorfismo no atañe a la clase o prototipo de la que provienen los objetos. Aun así, en los lenguajes basados en clases, es habitual (y en algunos tal vez sea el único modo) que dichos objetos pertenezcan a subclases pertenecientes a una misma jerarquía. Entonces, el polimorfismo debe verse como una forma flexible de usar un grupo de objetos (como si fueran sólo uno). Podría decirse que el polimorfismo en esencia refiere al comportamiento de los objetos, no a su pertenencia a una jerarquía de clases (o a sus tipos de datos).
Lo anterior se hace aún más evidente en lenguajes de programación orientada a objetos basados en prototipos, como Self, en los que las clases no existen.
Además, es importante remarcar que si un cierto grupo de objetos pueden utilizarse de manera polimórfica es porque, en última instancia, todos ellos saben responder a un cierto mensaje (o a varios), pero dado que esos mismos objetos generalmente contendrán otros métodos (que otros objetos en dicho grupo no contienen), difícilmente se pueda decir lisa y llanamente que los objetos son polimórficos; lo correcto es decir que esos objetos se pueden utilizar de modo polimórfico para un cierto conjunto de mensajes.
Un ejemplo. Podemos crear dos clases distintas: Pez y Ave que heredan de la superclaseAnimal. La clase Animal tiene el método abstracto mover que se implementa de forma distinta en cada una de las subclases (peces y aves se mueven de forma distinta). Entonces, un tercer objeto puede enviar el mensaje mover a un grupo de objetos PezAvepor medio de una variable de referencia de clase Animal, haciendo así un uso polimórfico de dichos objetos respecto del mensaje mover.
El concepto de polimorfismo, desde una perspectiva más general, se puede aplicar tanto a funciones como a tipos de datos. Así nacen los conceptos de funciones polimórficas ytipos polimórficos. Las primeras son aquellas funciones que pueden evaluarse o ser aplicadas a diferentes tipos de datos de forma indistinta; los tipos polimórficos, por su parte, son aquellos tipos de datos que contienen al menos un elemento cuyo tipo no está especificado.

Encapsulamiento de los atributos de una clase

Antes de nada, debe quedar claro que el encapsulamiento, igual que cualquier buen hábito de programación (como no poner goto, comentar, etc) es útil para código que más adelante se puede querer reutilizar o modificar, por otras personas o por uno mismo. Si yo hago un programa de marcianos y nunca jamas pienso volver a tocarlo, da igual que lo haga con gotos y sin comentar mientras me entere yo mismo mientras lo estoy haciendo y funcione. Pagaré este "pecado" si dentro de dos meses se me ocurre mejorarlo o quiero reaprovechar algo de su código para otro programa.
Comento esto porque el encapsulamiento, llevado a su extremo, como es el caso del punto final de interfaces, hace la programación un poco más complicada (hay que hacer más clases). Este esfuerzo sólo se ve recompensado si el código es muy grande (evitando recompilados innecesarios) o se va a reutilizar en un futuro (podremos extraer clases con menos dependencias de otras clases). Dicho esto, vamos al tema.
Cualquier curso de orientación a objetos nos dice que es mejor poner los atributos de una clase protegidos o privados (nunca públicos) y acceder a ellos a través de métodos públicos que pongamos en la clase. Veamos el motivo. Supongamos, por ejemplo, que nos piden un programa que permita llevar una lista de gente con sus fechas de nacimiento. Entre otras cosas, decidimos hacernos nuestra clase Fecha con varios métodos maravillosos de la siguiente manera.
class Fecha
{
   public:
      int anho; // El anho con cuatro cifras, ej. 2004
      int mes;  // El mes, de 1 a 12
      int dia;    // El dia, de 1 a 31
      void metodoMaravilloso1();
      void metodoMaravilloso2();
};
Ya hemos hecho la clase. Ahora hacemos el resto del código y en unos varios miles de líneas de código usamos directamente cosas como esta.
Fecha unaFecha;
unaFecha.anho = 2004;
unaFecha.mes = 1;
unaFecha.dia = 25;
Finalmente acabamos nuestro programa y todo funciona de maravilla. Unos días después nos dicen que el programa va a guardar tropecientas mil personas y que ocupan mucho los ficheros, que a ver si podemos hacer algo para remediarlo. ¡Vaya!, almacenamos una fecha con tres enteros. Si usamos el formato de la mayoría de los ordenadores, en el que la fecha es el número de segundos transcurridos desde el 1 de Enero de 1970 (lo que nos devuelve la función time()), basta con un entero.
Total, que manos a la obra, cambiamos nuestra clase para que tenga lo siguiente:
class Fecha
{
   public:
      /* Comentado por ineficiente
      int anho; 
      int mes; 
      int dia;   */
      long numeroSegundos;
      void metodoMaravilloso1();
      void metodoMaravilloso2();
};
Ya está hecho lo fácil. Ahora sólo hay que ir por las tropecientas mil líneas de código cambiando nuestras asignaciones y lecturas a los tres enteros anteriores por el nuevolong.
Hubiera sido mucho mejor si hubieramos hecho estos tres enteros protegidos y unos métodos para acceder a ellos. Algo como esto
class Fecha
{
   public:
      void tomaFecha (int anho, int mes, int dia);
      int dameAnho ();
      int dameMes ();
      int dameDia ();
      void metodoMaravilloso1();
      void metodoMaravilloso2();
   protected:
      int anho; // El anho con cuatro cifras, ej. 2004
      int mes;  // El mes, de 1 a 12
      int dia;    // El dia, de 1 a 31
};
Si ahora tenemos que hacer el mismo cambio, basta con cambiar los atributos protegidos. Los métodos tomaXXX() y dameXXX() se mantienen en cuanto a parámetros y valor devuelto, pero se modifica su código interno para que conviertan el año,mes y dia en un long de segundos y al revés. El resto del código no hay que tocarlo en absoluto.
Es incluso mejor hacer los atributos privados que protegidos. Haciéndolos protegidos, las clases hijas (las que heredan de Fecha) pueden acceder directamente a estos atributos. Cuando hagamos el cambio por un long, debemos cambiar también el código de las clases hijas. Si los atributos son privados y obligamos a las clases hijas a acceder a ellos a través de métodos, tampoco tendremos que cambiar el código de estas clases hijas.
El acceso a través de métodos es menos eficiente que hacerlo directamente, así que aunque siguiendo el principio de ocultación es mejor hacer atributos privados, por eficiencia en algunos casos quizás sea mejor hacerlos protegidos (o incluso públicos) a riesgo de tener que cambiar más líneas de código en caso de cambio.
OOP
En esta sección no se pretende dar una teoría completa de P.O.O. tan sólo se presentarán los conceptos necesarios para una correcta programación en C++ Builder.
La P.O.O. es un paradigma de programación que se fundamenta en los conceptos de objeto y clase. En primer lugar, definamos que entendemos por objeto y clase:
Objeto:Una entidad autónoma con una funcionalidad concreta y bien definida.
Clase:
 
Especificación de las características de un conjunto de objetos.
Un objeto es una instancia de una clase.
Los conceptos presentados en esta sección se ilustrarán usando un ejemplo que se irá completando poco a poco a medida que se introduzcan nuevos conceptos. Es más, este mismo ejemplo se emplea en las secciones dedicadas al tratamiento de excepciones y a la programación con hebras. Así, preparemos el camino creando un proyecto:
  • Crear un proyecto (File | New | Application)
  • Cambiar el nombre del formulario (Name=PpalFrm). Colocar un PaintBox de la página de componentes System que se llame PaintBox, con Align=alTop. Dejar espacio por debajo del PaintBox para colocar un botón.
  • Colocar un bevel de ancho 4 y alinearlo en lo alto (Align=alTop). La idea es que delimite la parte inferior del PaintBox.
  • Colocar un botón bit que permita terminar la ejecución del programa. El botón estará centrado horizontalmente en la parte inferior del formulario.
  • Guardar el código del formulario como Ppal.cpp y el proyecto como Ejemplo.bpr.
  • Crear una unidad (File | New | Unit). Guardarla con el nombre ObjGraf.cpp
  • Cuando se crea una unidad de esta manera se crean, en realidad, dos ficheros, uno con extensión .cpp y otro con extensión .h. Así, disponemos de dos ficheros: ObjGraf.h, que contendrá las declaraciones de las clases con las que vamos a trabajar, y ObjGraf.cpp, que contendrá la definición (implementación de los métodos) de éstas.
En ObjGraf.h:
//--------------------------------------------------

#ifndef ObjGrafH
#define ObjGrafH

// Definición de la clase TObjGraf

class TObjGraf {};

#endif

//--------------------------------------------------

Nótese que el nombre de la clase va precedido por una T, y, aunque no es obligatorio, si es muy recomendable ya que es una convención de C++ Builder que casi todos los nombres de clases vayan precedidos por T.
Muy Importante: Con el ejemplo anterior sólo conseguimos definir la clase, pero no se crea ningún objeto.

5.1. El Paradigma de la POO en C++
Existen cuatro principios básicos que cualquier sistema orientado a objetos debe incorporar, que se esquematizan en la figura 5.1.
Figura 5.1. Pilares de la POO.

5.2. Creación y Destrucción de Objetos
Ya se ha dicho que una clase es únicamente una especificación. Para poder utilizar la funcionalidad contenida en la misma, se deben instanciar las clases.

  1. Creación por Declaración.
  2. Un objeto se puede instanciar de una forma simple, declarando una variable del tipo de la clase.
    En Ppal.h:
    #include "ObjGraf.h"
    
    En Ppal.cpp:
    Pulsando dos veces en OnCreate de la pestaña Events del editor de objetos de PpalFrm:
    //--------------------------------------------------
    
    void __fastcall TPpalFrm::FormCreate(TObject *Sender)
    {
      TObjGraf ObjGraf1();
      TObjGraf ObjGraf2;
    }
    
    //--------------------------------------------------
    
    Aunque esta forma es posible, y bastante utilizada en la programación de C++ clásica, en C++ Builder se utiliza en muy contadas ocasiones. Esto es así por dos razones, fundamentalmente:
    1. La duración de los objetos suele ir más allá de una simple función o bloque. Debido al enfoque de la programación dirigida por eventos, suele ser habitual que un objeto se cree en un gestor de eventos y se destruya en otro.
    2. No se puede usar esta modalidad de creación con la VCL.
    Por lo tanto, nosotros no la utilizaremos.

  3. Creación Dinámica
  4. Es la forma habitual de crear objetos en C++ Builder, y se realiza mediante el operador new .
    Cuando usamos new para instanciar un objeto, se usa una variable que referencie o apunte al nuevo objeto creado (de otra manera éste quedaría totalmente inaccesible). En definitiva, se requiere la declaración previa de un puntero a objetos del tipo del que se va a crear.
    En Ppal.cpp:
    TObjGraf * ObjGraf; // Variable Global.
                        // ObjGraf es un puntero a objetos de tipo TObjGraf
    
    //--------------------------------------------------
    
    void __fastcall TPpalFrm::FormCreate(TObject *Sender)
    {
       ObjGraf = new TObjGraf;
    }
    
    //--------------------------------------------------
    
    ¡Cuidado! Cuando se utiliza esta forma de instanciación de clases es responsabilidad únicamente del programador la correcta destrucción de los mismos.

  5. Destrucción de objetos
  6. Cuando un objeto deja de ser útil hay que eliminarlo. De esta manera la aplicación recupera los recursos (memoria) que ese objeto había acaparado cuando se creó.
    La destrucción de objetos creados en tiempo de ejecución con new se realiza mediante el operador delete.
    En Ppal.cpp:
    Pulsando dos veces en OnDestroy de la pestaña Events del editor de objetos de PpalFrm:
    //--------------------------------------------------
    
    void __fastcall TPpalFrm::FormDestroy(TObject *Sender)
    {
       delete ObjGraf;
    }
    

CLASES EN C++
Ahora va a empezar un pequeño bombardeo de nuevas palabras reservadas de C++, pero no te asustes, no es tan complicado como parece.
La primera palabra que aparece es lógicamente class que sirve para definir una clase y para declarar objetos de esa clase. Su uso es parecido a la ya conocida struct:
class <identificador de clase> [<:lista de clases base>] {
   <lista de miembros>
} [<lista de identificadores de objetos>]; 
La lista de clases base se usa para derivar clases, de momento no le prestes demasiada atención, ya que por ahora sólo declararemos clases base.
La lista de miembros será en general una lista de funciones y datos.
Los datos se declaran del mismo modo en que lo hacíamos hasta ahora, salvo que no pueden ser inicializados, recuerda que estamos hablando de declaraciones de clases y no de definiciones de objetos. En el siguiente capítulo veremos el modo de inicializar las variables de un objeto.
Las funciones pueden ser simplemente declaraciones de prototipos, que se deben definir aparte de la clase pueden ser también definiciones.
Cuando se definen fuera de la clase se debe usar el operador de ámbito "::".
Lo veremos mucho mejor con un ejemplo.
#include <iostream> 
using namespace std;
 
class pareja {
   private:
      // Datos miembro de la clase "pareja"
      int a, b; 
   public:
      // Funciones miembro de la clase "pareja"
      void Lee(int &a2, int &b2);
      void Guarda(int a2, int b2) {
         a = a2;
         b = b2;
      }
};

void pareja::Lee(int &a2, int &b2) {
   a2 = a;
   b2 = b;
}

int main() {
   pareja par1;
   int x, y;
   
   par1.Guarda(12, 32);
   par1.Lee(x, y);
   cout << "Valor de par1.a: " << x << endl;
   cout << "Valor de par1.b: " << y << endl;

   return 0;
}
Nuestra clase "pareja" tiene dos miembros de tipo de datos: a y b.
Y dos funciones, una para leer esos valores y otra para modificarlos.
En el caso de la función "Lee" la hemos declarado en el interior de la clase y definido fuera, observa que en el exterior de la declaración de la clase tenemos que usar la expresión:
void pareja::Lee(int &a2, int &b2)
Para que quede claro que nos referimos a la función "Lee" de la clase "pareja". Ten en cuenta que pueden existir otras clases que tengan funciones con el mismo nombre, y también que si no especificamos que estamos definiendo una función de la clase "pareja", en realidad estaremos definiendo una función corriente.
En el caso de la función "Guarda" la hemos definido en el interior de la propia clase. Esto lo haremos sólo cuando la definición sea muy simple, ya que dificulta la lectura y comprensión del programa.
Además, las funciones definidas de este modo serán tratadas como inline, y esto sólo es recomendable para funciones cortas, ya que, (como recordarás), en estas funciones se inserta el código cada vez que son llamadas.

Especificadores de acceso

^
Dentro de la lista de miembros, cada miembro puede tener diferentes niveles de acceso.
En nuestro ejemplo hemos usado dos de esos niveles, el privado y el público, aunque hay más.
class <identificador de clase> {
  public:
   <lista de miembros>
  private:
   <lista de miembros>
  protected:
   <lista de miembros>
};

Acceso privado, private

Los miembros privados de una clase sólo son accesibles por los propios miembros de la clase y en general por objetos de la misma clase, pero no desde funciones externas o desde funciones de clases derivadas.

Acceso público, public

Cualquier miembro público de una clase es accesible desde cualquier parte donde sea accesible el propio objeto.

Acceso protegido, protected

Con respecto a las funciones externas, es equivalente al acceso privado, pero con respecto a las clases derivadas se comporta como público.
Cada una de éstas palabras, seguidas de ":", da comienzo a una sección, que terminará cuando se inicie la sección siguiente o cuando termine la declaración de la clase. Es posible tener varias secciones de cada tipo dentro de una clase.
Si no se especifica nada, por defecto, los miembros de una clase son privados.

Palabras reservadas usadas en este capítulo

^
classprivateprotected y public.

Comentarios de los usuarios (8)

Ruben
2010-04-17 12:07:30
¿Se prodria poner algun ejercicio de clases? osea, para entender mejor el tema.
Hasta ahora con los problemas de los temas anteriores todo llegaba a entenderse mejor, y ayudaba mucho a la memoria (eran mas facil de recordarlos) llevar a la practica lo aprendido.
Esteban
2012-04-18 04:56:23
Hola,
¿Podrian explicar el significado de la sentencia "class" en el siguiente ejemplo?
class otraclase;

class derivada : public base
{

public:
        virtual void unafuncion(const otraclase*);

};
Y cual sería la diferencia con incluir la clase "otraclase" de la siguiente forma:
#include "otraclase.hh"

class derivada : public base
{

public:
        virtual void unafuncion(const otraclase*);

};
En ambos casos la clase "otraclase" esta dividida en la cabecera otraclase.hh y la implementacion de sus funciones dentro de otraclase.cc
Muchas gracias y felicitaciones por el curso que esta buenisimo.
Steven R. Davidson
2012-04-18 06:20:06
Hola Esteban,
En la primera versión del ejemplo, indicamos al compilador que el identificador (nombre) 'otraclase' es una clase. No definimos la clase, por lo que es una definición parcial y por tanto, incompleta. Esto se llama "declaración adelantada". En este caso, no hay una clara ventaja de hacer esto.
En la segunda versión, incluyes el contenido del fichero "otraclase.hh", que seguramente contendrá la definición completa de la clase, aunque como dices seguramente no contiene la implementación de cada función miembro, las cuales estarán en el fichero objeto o posiblemente en el fichero fuente, "otraclase.cc".
La idea tras la declaración adelantada es cuando estemos definiendo clases interconectadas. Una definición de una clase requiere el uso de otra clase, pero la definición de esta otra clase requiere el uso de la primera clase. Para ayudar en resolver este tipo de problemas, C++ acepta una declaración adelantada de una clase, y así podemos referirnos a ella sin tener que definir toda la clase previamente. Por ejemplo,
class Jugador
{
  ...
  void atacado( Enemigo *ptr );
  void atacando( Enemigo *ptr );
};

class Enemigo
{
  ...
  void atacado( Jugador *ptr );
  void atacando( Jugador *ptr );
};
El problema como vemos es que para 'Jugador', necesitamos saber qué es 'Enemigo', ya que mencionamos esta entidad, pero el compilador no sabe qué es. No podemos invertir el orden de las definiciones, porque 'Enemigo' requiere 'Jugador', que aún no se habría definido.
La solución es usar una declaración adelantada de 'Enemigo', para que podamos usarla en 'Jugador', para luego definirla completamente. Esto es,
class Enemigo;  // Enemigo es una clase

class Jugador
{
  ...
  void atacado( Enemigo *ptr );
  void atacando( Enemigo *ptr );
};

class Enemigo
{
  ...
  void atacado( Jugador *ptr );
  void atacando( Jugador *ptr );
};
INTERNET DE LAS COSAS 
¿Se imagina un frigorífico que le avise de la fecha de caducidad de los alimentos que contiene? ¿O que las zapatillas que usa para hacer deporte registren "en la nube" las estadísticas de cuánto corre cada semana y a qué velocidad? ¿Y que los inodoros analicen su orina y le recomienden la dieta alimentaria que más le conviene seguir? ¿Qué pasaría si el cepillo de dientes le alertara de cualquier pequeña caries y pidiera por usted cita en el dentista? Son algunas posibles aplicaciones de lo que se conoce comoel "Internet de las cosas" o "Internet de los objetos" (IoT, por sus siglas en inglés), un concepto que nació en el Instituto de Tecnología de Massachusetts (MIT). Se trata una revolución en las relaciones entre los objetos y las personas, incluso entre los objetos directamente, que se conectaran entre ellos y con la Red y ofrecerán datos en tiempo real. O dicho de otro modo, se acerca la digitalización del mundo físico. 

Gracias al sistema RFID (siglas de radio frequency identification, es decir,, «identificación por radiofrecuencia»), bastará con integrar un chip de pocos milímetros en cualquier objeto del hogar, del trabajo o de la ciudad para poder procesar y transmitir información a partir de él constantemente. Se calcula que en 2020, entre 22.000 y 50.000 millones de dispositivos se conectarán a Internet con el fin de proporcionar a los ciudadanos una serie de servicios y aplicaciones inteligentes sin precedentes.

Según Hans Vestberg , CEO de Ericsson, las repercusiones serán considerables: «Si una persona se conecta a la red, le cambia la vida. Pero si todas las cosas y objetos se conectan, es el mundo el que cambia.

¿Qué es Business Intelligence?

Business Intelligence es la habilidad para transformar los datos en información, y la información en conocimiento, de forma que se pueda optimizar el proceso de toma de decisiones en los negocios.
Datos, información y conocimiento
Desde un punto de vista más pragmático, y asociándolo directamente con las tecnologías de la información, podemos definir Business Intelligence como el conjunto de metodologías, aplicaciones y tecnologías que permiten reunir, depurar y transformar datos de los sistemas transaccionales e información desestructurada (interna y externa a la compañía) en información estructurada, para su explotación directa (reporting, análisis OLTP / OLAP, alertas...) o para su análisis y conversión en conocimiento, dando así soporte a la toma de decisiones sobre el negocio.
La inteligencia de negocio actúa como un factor estratégico para una empresa u organización, generando una potencial ventaja competitiva, que no es otra que proporcionar información privilegiada para responder a los problemas de negocio: entrada a nuevos mercados, promociones u ofertas de productos, eliminación de islas de información, control financiero, optimización de costes, planificación de la producción, análisis de perfiles de clientes, rentabilidad de un producto concreto, etc...
Los principales productos de Business Intelligence que existen hoy en día son:
Por otro lado, los principales componentes de orígenes de datos en el Business Intelligence que existen en la actualidad son:
Los sistemas y componentes del BI se diferencian de los sistemas operacionales en que están optimizados para preguntar y divulgar sobre datos. Esto significa típicamente que, en un datawarehouse, los datos están desnormalizados para apoyar consultas de alto rendimiento, mientras que en los sistemas operacionales suelen encontrarse normalizados para apoyar operaciones continuas de inserción, modificación y borrado de datos. En este sentido, los procesos ETL (extracción, transformación y carga), que nutren los sistemas BI, tienen que traducir de uno o varios sistemas operacionales normalizados e independientes a un único sistema desnormalizado, cuyos datos estén completamente integrados.
En definitiva, una solución BI completa permite:
* Observar ¿qué está ocurriendo?
* Comprender ¿por qué ocurre?
* Predecir ¿qué ocurriría?
* Colaborar ¿qué debería hacer el equipo?
* Decidir ¿qué camino se debe seguir?
        Ciclo de la información en la empresa