Uno es profesional, uno es hombre (no ratón), pero a veces por las prisas del trabajo, es mejor la comodidad de instalar nuestros programas desde algún repositorio público como sunfreeware.com o blastwave.org en vez de compilarlos a "manita". Todo sea para cumplir adecuadamente una fecha de entrega y después de todo... Cuando estamos en Linux, ¿no hacemos lo propio con los rpms, yums o apt-gets?
Paquetes en sunfreeware
Podemos consultar todos los paquetes que están a nuestra disposición en el ftp de sunfreeware:
ftp://ftp.sunfreeware.com/pub/freeware/i386/10/
E instarlos usando el comando pkgadd -d. Por su puesto, revisando primero que no estén ya instalados con el comando pkginfo:
Si ya está instalado podemos obtener más información con:
Por ejemplo, instalando la biblioteca boost
Como usuario root:
cd /tmp
wget ftp://ftp.sunfreeware.com/pub/freeware/i386/10/boost-1.34.1-sol10-x86-local.gz
gunzip boost-1.34.1-sol10-x86-local.gz
pkgadd -d boost-1.34.1-sol10-x86-local
Y listo, fué todo.
Supongamos que tenemos las siguientes clases:
#include <iostream>
#include <boost/shared_ptr.hpp>
using namespace std;
class Base {
public:
virtual void imprime() { cout <<"Función imprime de la Clase Base" <<endl; }
virtual ~Base() { cout <<"Destructor de la Clase Base" <<endl; }
};
typedef boost::shared_ptr<Base> base_ptr;
class Derivada : public Base {
public:
virtual void imprime() { cout <<"Función imprime de la Clase Derivada" <<endl; }
virtual ~Derivada() { cout <<"Destructor de la Clase Derivada" <<endl; }
};
typedef boost::shared_ptr<Derivada> derivada_ptr;
Y queremos hacer esto:
int main
() {
derivada_ptr derivada( new Derivada );
base_ptr base( derivada );
base->imprime();
// La siguiente línea no va a compilar:
derivada_ptr regreso( base );
return EXIT_SUCCESS;
}
En la tercera declaración, nos va a marcar este error al compilar:
/usr/include/boost/shared_ptr.hpp:194: error: conversión inválida de ‘Base* const’ a ‘Derivada*’
Obviamente, necesitamos un casting. La forma para hacerlo sería así:
int main
() {
derivada_ptr derivada( new Derivada );
base_ptr base( derivada );
base->imprime();
// Ahora si compila:
derivada_ptr regreso( boost::static_pointer_cast<Derivada>( base ) );
return EXIT_SUCCESS;
}
Al ejecutar el programa, obtenemos esta salida:
Función imprime de la Clase Derivada
Destructor de la Clase Derivada
Destructor de la Clase Base
Como se ve, el smart pointer funcionó a la perfección a pesar de todas las transformaciones.
Boost es una excelente librería con todo lo que un buen programador de C++ pudiera necesitar. Además está desarrollada para hacer la programación sencilla, elegante y rápida. A continuación incluyo un ejemplo simple de una clase que encapsula el manejo de hilos usando Boost y que puede servir de prototipo en diversos proyectos:
#include <iostream>
#include <boost/bind.hpp>
#include <boost/thread/thread.hpp>
class Hilo {
public:
Hilo() : keepgoing( true ), thread( boost::bind( &Hilo::do_work, this ) ) { };
~Hilo() {
keepgoing = false;
// Necesitamos esperar a que el hilo se acabe
thread.join();
}
private:
bool keepgoing;
boost::thread thread;
void do_work() {
// Aquí es donde se lleva a cabo toda la acción.
while( keepgoing ) {
std::cout <<"Hilo" << std::endl;
sleep(1);
}
}
};
int main( void ) {
Hilo *hilo = new Hilo();
sleep(20);
delete hilo;
return EXIT_SUCCESS;
}
El programa lo podemos compilar con:
g++ -O2 -o main main.cpp -lboost_thread-mt
Notas:
- Como se puede ver esta aproximación es más parecida a como le hace C# que Java.
- El hilo comienza al crearse el objeto.
- No hay manera de controlar manualmente el tamaño del stack
- Si no hay recursos suficientes se lanza una excepción y el objeto no se crea.