quinta-feira, 26 de junho de 2014

Compilar C++ Linux

Primeiramente antes de compilar um programa vamos precisar do programa, no caso, vou utilizar um programa que não faz nada, simplesmente implementa a função main, já que a ideia é demonstrar como compilar e não como programar.

Estou utilizando o S.O. Fedora, provavelmente os comandos utilizados não serão diferentes dos utilizados em outras distribuições de Linux ou em um Mac. Para compilar utilizarei o comando g++.

//blog.cc
int main(int argc, char ** argv){
 return 1;
}

O exemplo acima deve estar em um arquivo chamado blog.cc, o .cc ajuda a diferenciar o c puro do c++, normalmente os fontes de c++ utilizam extensão cpp ou cc, enquanto os de c puro utilizam somente o c.

Depois do arquivo criado só é necessário rodar o comando abaixo no diretório do arquivo.
g++ blog.cc -o blog

Como o programa que estamos compilando não utiliza nenhum recurso de C++, ele pode ser compilado como um programa escrito em c puro, neste caso pode ser executado o comando abaixo.
gcc blog.cc -o blog

O próximo programa também bem simples, somente define uma classe Object com alguns métodos e o instancia de três formas diferentes na função main. Este já é um programa que utiliza recursos de C++ sendo necessário compilar com o g++.

//blog.cc
#include <string>
#include <iostream>

using namespace std;

class Object {
private:
 string name; 
public:
 Object(){
  cout << "Construtor" << endl;
 }
 Object(const Object& object){
  cout << "Construtor de Cópia" << endl;
 }
 virtual ~Object(){
  cout << "Destrutor" << endl;
 }
};

int main(int argc, char ** argv){
 Object obj;
 Object obj2(obj);
 Object * p = new Object();
 delete p;
 p = new Object(obj2);
 delete p;
 return 1;
}

Porém desta forma a definição da classe fica no mesmo arquivo, o principal, o que é inviável em grandes aplicações, então vou demonstrar uma forma de separar as classes C++ em arquivos diferentes.

Uma forma simples, seria criar uma biblioteca para a classe e importá-la no arquivo principal, como demonstrado no exemplo abaixo.
//blog.cc
#include "object.hh"

int main(int argc, char ** argv){
 Object obj;
 Object obj2(obj);
 Object * p = new Object();
 delete p;
 p = new Object(obj2);
 delete p;
 return 1;
}
//object.hh
#ifndef __OBJECT_HH__
#define __OBJECT_HH__

#include <iostream>
#include <string>

using namespace std;

class Object {
private:
 string name; 
public:
 Object(){
  cout << "Construtor" << endl;
 }
 Object(const Object& object){
  cout << "Construtor de Cópia" << endl;
 }
 virtual ~Object(){
  cout << "Destrutor" << endl;
 }
};

#endif

Para compilar esse exemplo são necessários os dois arquivos blog.cc e object.hh, depois de criados basta compilar com o comando abaixo. Antes de executar o comando se certifique que os dois arquivos estão no mesmo diretório.
g++ blog.cc -o blog


Porém desta forma sempre que o arquivo principal for compilado, todas as bibliotecas importadas serão compiladas novamente, podendo ficar um pouco custoso em projetos grandes. Para evitar essa recompilação, é possível criar objetos compilados que podem ser utilizados na compilação final.

Para compilar somente uma classe C++, primeiramente será necessário separar o cabeçalho da classe de seu corpo,ou seja, sua interface de sua implementação, como demonstrado no exemplo abaixo.
//blog.cc
#include <string>
#include <iostream>

using namespace std;

class Object {
private:
 string name; 
public:
 Object();
 Object(const Object& object);
 virtual ~Object();
};


Object::Object(){
 cout << "Construtor" << endl;
}

Object::Object(const Object& object){
 cout << "Construtor de Cópia" << endl;
}

Object::~Object(){
 cout << "Destrutor" << endl;
}

int main(int argc, char ** argv){
 Object obj;
 Object obj2(obj);
 Object * p = new Object();
 delete p;
 p = new Object(obj2);
 delete p;
 return 1;
}
Neste exemplo ainda está tudo em um arquivo só, porém a classe object foi separada entre cabeçalho e corpo.
Depois o cabeçalho da classe deve ser colocado em uma biblioteca e seu corpo em um arquivo de c++, sendo que o arquivo do corpo deve importar a biblioteca com seu cabeçalho. A função main pode ser colocada em um outro arquivo.
Abaixo estão os exemplos dos três arquivos, object.hh com o cabeçalho da classe object, object.cc com o corpo da classe object e o arquivo blog.cc que implementa a função main e utiliza a classe object.

//blog.cc
#include "object.hh"

int main(int argc, char ** argv){
 Object obj;
 Object obj2(obj);
 Object * p = new Object();
 delete p;
 p = new Object(obj2);
 delete p;
 return 1;
}
//object.hh
#ifndef __OBJECT_HH__
#define __OBJECT_HH__

#include <string>

using namespace std;

class Object {
private:
 string name; 
public:
 Object();
 Object(const Object& object);
 virtual ~Object();
};

#endif
//object.cc
#include "object.hh"

#include <iostream>

Object::Object(){
 cout << "Construtor" << endl;
}

Object::Object(const Object& object){
 cout << "Construtor de Cópia" << endl;
}

Object::~Object(){
 cout << "Destrutor" << endl;
}

Para compilar somente a classe é necessário utilizar a opção de compilação -c, caso contrário o compilador emite um erro, pois ele tentará criar um executável, mas como não existe a função main isso não é possível. A opção -c diz para o compilador somente compilar. Os comandos para compilar estão logo abaixo.

g++ -c object.cc -o object.o
g++ blog.cc -o blog object.o

Primeiramente foi compilada a classe object gerando um arquivo de saída object.o, o nome do aquivo de saída foi determinado pela opção -o. Em seguida foi compilado o arquivo com a função main, gerando um arquivo de saída blog. O arquivo object.o foi passado como parâmetro de compilação, assim o compilador o utiliza para gerar o executável blog. Sem passar o object.o como parâmetro o compilador terá acesso somente ao cabeçalho da classe object, já que a implementação de seus métodos estão no arquivo object.cc, causando um erro de compilação. Porém a implementação dos métodos estão compiladas no arquivo object.o, assim o compilador utiliza esse arquivo para saber o corpo dos métodos.

Para facilitar bastante a vida dos programadores, existe um recurso que ajuda muito na compilação, que é o make, ele é basicamente uma linguagem de script feita para compilar, provavelmente será visto em um próximo post.

Obrigado!.

segunda-feira, 23 de junho de 2014

Hot Tips: cURL - O que???

Você que está no meio da programação, desenvolvimento, sistemas web, etc; provavelmente já ouviu falar de cURL... Não??? Bom então nesse caso é bom começar do zero. Quando se trata de Web e aplicações que trabalham com internet, separa-se em 2 "lados" da moeda o Cliente-Side e o Server-Side, o cliente-side é a parte da aplicação que roda no computador, tablet, smartphone do usuário do sistema, e o server-side o local onde recebe requisições do client-side, pedindo alguma informação, ou enviando algo para ser salvo por exemplo. E é exatamente nesse ponto que nossa querida libcurl entra em ação.

Um cURL é responsável pelas requisições feitas para um server-side, uma forma de comunicaçao entre os dois lados, onde é possível trabalhar com header's, paramêtros, dentre outras configurações como métodos de requisição (POST,PUT,GET,DELETE....).

Abaixo um exemplo de requisição feito em cURL para nosso blog:

variavel = "conteudo da variavel"
curl 'http://programandonoaquario.blogspot.com.br/' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -H 'Connection: keep-alive' -H 'Accept-Encoding: gzip,deflate,sdch' -H 'Accept-Language: pt-BR,pt;q=0.8,en-US;q=0.6,en;q=0.4' -H 'User-Agent: Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.115 Safari/537.36' --compressed

Para usar o cURL no Linux por linha de comando, em algumas distribuições é necessário instalar
  • sudo apt-get install curl
Para habilitar o modulo no PHP
  • apt-get install php5-curl
Ok, agora você já sabe como funciona uma requisição em cURL, nosso próximo assunto tratará de um tipo de sistema que utiliza muito cURL, as API's.

Abraços e até o proximo!!!

sexta-feira, 13 de junho de 2014

Introdução a Programação parte 2: Variáveis

Dando continuidade a Introdução a Programação, hoje vamos ver variáveis.
Uma variável é um "lugar" onde se pode colocar as coisas,no caso do python este "lugar" pode ter qualquer coisa.

variavel = "conteudo da variavel"
print variavel

No exemplo acima é inserido em uma variável o texto "conteudo da variavel", em seguida o comando "print" escreve a variável, não o nome da variável mas sim seu conteúdo.
Os nomes das variáveis são definidos pelos programadores tendo algumas restrições das linguagens, normalmente o primeiro caractere tem que ser uma letra de 'a' a 'z' ou '_', podendo ser maiúsculo ou minusculo e os demais caracteres podem ser letras ou números.
Exemplos de variáveis válidas:
  • cafe
  • resultado
  • nome_do_cliente
  • nomeDoCliente
  • v8

Exemplos de variáveis não válidas:
  • 1valor
  • #var
  • 123

Em algumas linguagens as variáveis podem ter caracteres especiais, como letras acentuadas, porém são poucas estas linguagens, então por padrão é bom evitar o uso de acentos.
Uma variável é na verdade um endereço de memoria ou um espaço da memoria do computador, onde podem ser armazenados os valores.
Infelizmente ou felizmente, uma variável é somente uma coisa por vez e quando utilizamos o simbolo '=' estamos utilizando o comando de atribuição, estamos atribuindo um valor a uma variável.
Realizando a atribuição, o valor anterior da variável é perdido como será demonstrado no exemplo abaixo.
oNomeQueVoceQuiser = "Programando fora do Aquario"
oNomeQueVoceQuiser = "Programando no Aquario"

print oNomeQueVoceQuiser


Algumas linguagens de programação não fazem distinção de letras maiúsculas e minusculas, ou seja, uma variável chamada "clienteNome" também pode ser chamada de "ClienteNome". Mas este não é o caso do python, como será demonstrado no próximo exemplo.

programandoNoAquario = 1
programandonoaquario = 2
PROGRAMANDONOAQUARIO = 3

print programandoNoAquario,programandonoaquario,PROGRAMANDONOAQUARIO


Devido a esta distinção podemos chamar o python de uma linguagem Case Sensitive.
Com a utilização de variáveis, podemos simplificar o entendimento de alguns programas simplesmente dando bons nomes as variáveis, ou segmentando os problemas.
raio = 5
pi = 3.14159
diametro = raio * 2
area = pi * raio * raio
perimetro = 2 * pi * raio

print "Sendo PI = ",pi
print "Sendo o raio do circulo = ",raio
print "Diametro = ",diametro
print "Area = ",area
print "Perimetro = ",perimetro


No exemplo acima é demonstrado como o uso de nomes adequados para variáveis, pode situar o leitor do código, ajudando a descobrir a verdadeira intenção do código.

Para quem quiser se aprofundar na linguagem python, segue um link de um ótimo Tutorial de Python.

Obrigado!

sexta-feira, 6 de junho de 2014

Introdução a Programação

Programar é basicamente descrever como realizar alguma ação, programar computadores é então, descrever de uma forma que o computador possa entender e executar a ação descrita.

Normalmente as descrições das ações são semelhantes ao que chamamos de algoritmos, que é algo que estamos mais acostumados do que imaginamos. Quando pensamos em uma sequencia de ações para realizar alguma coisa, é basicamente um algoritmo. Por exemplo para fazer café:

  • Colocar o filtro na cafeteira
  • Colocar água na cafeteira
  • Colocar pó de café, uma colher a cada duas xícaras de água
  • Ligar a cafeteira
  • Aguardar


Um outro exemplo poderia ser uma receita qualquer, onde são descritos os ingredientes necessários e em seguida há um texto quase que um passo a passo, descrevendo uma sequencia de operações que devem ser seguidas para realizar a receita. No caso da receita uma pessoa descreveu para outra pessoa como realizar alguma coisa, já na programação de computadores é uma pessoa descrevendo para um computador.

Para uma pessoa descrever algo para outra pessoa ou simplesmente conversar, é necessário que elas entendam o que cada uma diz, para isso existem as linguagens, como no nosso caso o português e muitas outras, com os computadores assim como com as pessoas existem diversas linguagens.

Hoje pretendo utilizar a linguagem Python, escolhi essa linguagem por ser uma linguagem bem simples para exemplos pequenos e ser de fácil instalação, para quem não quiser instalar nada, também é possível testar os códigos em Python no site codepad.

Vou iniciar com um exemplo bem simples e clássico, um programa que escreve na tela “Hello World”.


print "Hello World"


Neste simples exemplo, utilizamos praticamente duas coisas, um comando de computador para escrever (print) e o texto que gostaríamos de escrever (Hello World). As aspas duplas são utilizadas justamente para o computador conseguir diferenciar o que é um comando, do que é texto.

Vamos então para um outro exemplo, a maioria das linguagens de computador conseguem facilmente representar operações matemáticas, como será demonstrado no próximo exemplo.


print 3 + 5
print 7 - 11
print 3 * 5
print 15 / 3


Neste exemplo o que será impresso na tela será o resultado das operações matemáticas e não as próprias operações, como as operações não estão entre aspas duplas o computador irá entender as operações como comandos e não como texto. No exemplo abaixo é impresso as operações, pois elas estão entre aspas duplas sendo consideradas textos e não comandos.


print "3 + 5"
print "7 - 11"
print "3 * 5"
print "15 / 3"


Para finalizar por hoje será feito um programa que imprime algumas operações e seus resultados.


print "3 + 5 =",3+5
print "7 - 11 =",7-11
print "3 * 5 =",3*5
print "15 / 3 =",15/3


Agora o comando “print” imprime duas coisas por vez, o texto entre aspas e o resultado da operação, um detalhe importante é a utilização da vírgula realizando uma separação. Assim como no português, que utilizamos vírgulas para separar algumas palavras dentro de uma sequencia de palavras (café, açúcar, caneca) a linguagem Python adotou uma notação semelhante.

Espero que com isso seja possível ter um pouco de entendimento do que é programação. Para programar computadores é simplesmente necessário saber descrever o que deseja ser realizado utilizando uma linguagem apropriada.

Para qualquer dúvida faça um comentário, assim posso tentar esclarecer essa dúvida e melhorar o post para que outros possam entender melhor. E se você é iniciante de programação, ou está começando a aprender agora faça um comentário, isso ajudará a incentivar continuações para essa introdução.

Obrigado!

Próxima parte...

domingo, 1 de junho de 2014

Herança Virtual em C++

Antes de falar sobre a herança virtual em C++, é preciso esclarecer o motivo de seu uso, que está intimamente ligado com uma das complicações da herança múltipla.

Algumas linguagens orientada a objeto resolveram não implementar a herança múltipla, substituindo esse recurso pelo uso de interfaces. Por exemplo em Java, uma classe não pode herdar duas classes ou mais, porém pode implementar quantas interfaces desejar. Em C++ como foi feito a implementação da herança múltipla, não existe a necessidade das interfaces, já que uma classe pode herdas diversas outras classes.

Em Java, se duas interfaces diferentes tiverem métodos com a mesma assinatura e uma classe qualquer implementar as duas interfaces, não existirá problema algum, afinal a implementação dos métodos é responsabilidade da classe que está “herdando” estas interfaces.

Em C++ é possível que uma classe herde de outras duas, que possuam métodos ou até mesmo atributos com os mesmos nomes, isso se torna algo conflitante, ainda por cima é possível que as duas classes herdadas já façam herança de outras classes, podendo ter até uma classe em comum.

Imagine a seguinte situação, classe A sem nenhuma herança, classes B e C herdando de A e uma classe D herdando de B e C. Neste caso há alguns questionamentos, uma instância de D equivale a quantas instâncias de A? Afinal ela herda A por B e por C. Acredito que exista casos em que a intenção seja duas instâncias, já alguns outros que seja apenas uma.

Para isso o C++ utiliza a herança virtual, com ela pode ser especificado como resolver esse tipo de herança. No exemplo abaixo foi feita a herança de forma normal, sem a utilização da herança virtual.

#include <iostream>

using namespace std;

class A {
private:
    static int contador;
public:
    A(){
        A::contador++;
        cout << "Construtor do A  ("<< A::contador <<")"<< endl;
    }
    virtual ~A(){
        cout << "Destrutor do A (" << A::contador << ")" << endl;
        A::contador--;
    }
};

int A::contador = 0;

class B : public A {
public:
    B(){
        cout << "Construtor do B" << endl;
    }
    virtual ~B(){
        cout << "Destrutor do B " << endl;
    }
};

class C : public A {
public:
    C(){
        cout << "Construtor do C" << endl;
    }
    virtual ~C(){
        cout << "Destrutor do C " << endl;
    }
};


class D : public B,C {
public:
    D(){
        cout << "Construtor do D" << endl;
    }
    virtual ~D(){
        cout << "Destrutor do D" << endl;
    }
};


int main(int argc, char ** argv){
    D d;
}

Se observada a saída deste programa, pode ser percebido que uma instância da classe D é na verdade duas instâncias da classe A, como se D fosse composto por uma instância da classe B e uma instância da classe C.
No próximo exemplo a herança de B e C para A foi feita de forma virtual, tornando a saída do programa um pouco diferente.
#include <iostream>

using namespace std;

class A {
private:
    static int contador;
public:
    A(){
        A::contador++;
        cout << "Construtor do A  ("<< A::contador <<")"<< endl;
    }
    virtual ~A(){
        cout << "Destrutor do A (" << A::contador << ")" << endl;
        A::contador--;
    }
};

int A::contador = 0;

class B : virtual public A {
public:
    B(){
        cout << "Construtor do B" << endl;
    }
    virtual ~B(){
        cout << "Destrutor do B " << endl;
    }
};

class C : virtual public A {
public:
    C(){
        cout << "Construtor do C" << endl;
    }
    virtual ~C(){
        cout << "Destrutor do C " << endl;
    }
};


class D : public B,C {
public:
    D(){
        cout << "Construtor do D" << endl;
    }
    virtual ~D(){
        cout << "Destrutor do D" << endl;
    }
};


int main(int argc, char ** argv){
    D d;
}

Neste caso uma instância de D representa apenas uma instância de A, como se a instância de B e de C que compõem a instância de D, fossem compostas pela mesma instância de A.

Obrigado!