Um introdução à Programação Orientada a Objetos em C++ (parte III)

« Leia a parte II

Funções membro

É ótimo saber que já conseguimos declarar algumas variáveis. A questão, agora, é como fazer um bom uso delas? A resposta está nas funções. No C++ classes podem ter funções membro – que são declaradas de modo similar às variáveis membro. Vamos usar um exemplo para dar uma idéia melhor do seu funcionamento.
Imagine um quadrado. Primeiro temos que modelar os dados com base nos atributos de um quadrado. Ele tem comprimento, largura e, claro, área. Acreditamos que você já saiba encontrar a área de um quadrado, multiplicando o comprimento pela largura. Esta tarefa pode ser feita por uma função membro:

c++, programação orientada a objetos
Clique na imagem para ampliar.

Este exemplo deve oferecer o resultado “10”. A classe quadrado é muito similar à classe casa, vista anteriormente.
Em seguida, vamos declarar a função area(), que vai retornar um valor int. Você a declara exatamente como a declararia fora de uma classe. Neste caso, fazemos com que area() retorne o resultado da multiplicação do comprimento pela largura e terminamos a classe. A seguir, iniciamos a função main(), que se explica por si mesma.

Definição das funções por fora da definição de classe

Se você tiver uma “penca” de funções para inserir em uma classe, o seu código, obviamente, poderá ficar bagunçado e difícil de entender. Para evitar que isto ocorra, usamos algo chamado operador de resolução do escopo.
Digamos que o que queremos é declarar a função area() fora da nossa definição original da função. Em primeiro lugar, gostaríamos de declarar a classe quadrado, e dentro dela a função area(), como mostrado acima. No entanto, não é interessante inserir o código de função neste ponto, de forma que a definição da classe ficaria assim:

class quadrado
{
public:
	int comprimento, largura;
	int area();
};

Para definir a area() da função membro do lado de fora da definição de classe, faríamos isto aqui:

int quadrado::area()
{
	return comprimento*largura;
}

Este código deverá produzir o mesmo resultado.

Público ou privado?

A velha dicotomia também encontra um lugar para ser discutida aqui. Quando o assunto é a definição de funções membro, você deve aprender a diferença entre membros públicos ou privados de uma classe.
Os membros declarados públicos podem ser acessados de qualquer função de dentro do programa. Podemos explicar isto através de um exemplo. Vamos supor que tenhamos declarado a classe quadrado tal como ela estava anteriormente e tivéssemos tentado acessar a variável comprimento de dentro da função main(), que não é uma função membro da classe:

Clique, para abrir a imagem em outra janela.
Clique, para abrir a imagem em outra janela.

O compilador não terá problemas para entender isto e irá dar o valor 2, como resultado. contudo, se mudarmos a classe quadrado para que se parecesse tal como abaixo, com todos os membros privativos:

class quadrado
{
private:
	int comprimento, largura;
	int area();
};

Se tentarmos rodar o código da função main(), acima, o compilador irá gerar um erro. Membros privados só podem ser acessados dentro de suas funções membro.

Construtores de classe

Temos este método para declarar o valor de cada variável membro de uma classe, abaixo – que me parece um tanto contraprodutivo:

main()
{
   quadrado meu_quadrado;
   meu_quadrado.comprimento=2
   meu_quadrado.largura=3
}

Para cada membro de meu_quadrado, temos que declarar separadamente o seu valor inicial. É claro que não é somente tedioso, mas também é fácil errar ao “pular”, sem perceber, a inicialização de cada membro. E isto vai ficando pior à medida em que as classes vão ficando mais complexas.
Uma maneira de contornar o problema é usar um construtor de classes &emdash; que consiste em uma função inicializada aonde quer que a classe seja usada:

Clique na imagem para ampliar
Clique na imagem para ampliar

Aqui, o resultado previsível é 10.
Primeiro declaramos o construtor de classes, dando-lhe o mesmo nome que a própria classe já tinha. Daí em diante, esta função vai executar-se a cada vez que a classe for usada. A declaramos de forma que ela tenha 2 valores, ambos do tipo int.
A próxima mudança vem na função main(). A cada vez que se declara um objeto como sendo do tipo quadrado, adicionamos uma definição de função. Neste caso, demos às variáveis comprimento1 e comprimento2 os valores de 5 e 2. O construtor então pega estas duas variáveis e atribui seus valores às variáveis membro comprimento e largura.

Arrays e Classes

Claro que você pode usar arrays com classes – o que abre a possibilidade para declarar muito mais variáveis em um período de tempo menor. Vamos ver um exemplo:

Clique, para abrir a imagem em nova janela.
Clique, para abrir a imagem em nova janela.

Não há nada complicado neste nosso último exemplo. Analise-o cuidadosamente 😉
Até a próxima!

Fontes: An Introduction to Object-Oriented Programming in C++
OOP in Wikipedia
Leia mais artigos de programação.

Uma introdução à Programação Orientada a Objetos em C++ (parte II)

« Leia a parte I

O que você precisa ter e para quem estamos escrevendo

Vai contra os nossos princípios obrigar as pessoas a comprar software ou hardware novo apenas para aprender coisas novas. Por isto, todo o artigo é baseado em softwares livres que podem ser baixados legalmente e gratuitamente da Internet.
Desta forma, todos os exemplos usados aqui podem ser compilados com o GNU C++. Este programa pode ser baixado livremente da Internet. No caso de você estar usando o Linux, como eu, você provavelmente já terá tudo do que precisa instalado na sua máquina.

Galera do Ubuntu

Algumas distros não vêm com o g++ instalado por padrão. Quem usa uma distro baseada no Debian, pode instalar rapidamente com o seguinte comando:

sudo apt-get install g++

😉 (dependendo da sua conexão, não dará tempo nem de ir buscar um cafezinho… )
Um bom editor de textos será muito útil. No Ubuntu, bem como em muitas outras distros Linux, é muito comum já vir instalado o nano, que é modo texto e tem realçe de sintaxe (syntax highlighting). Qualquer outro pode ser usado, contudo.

Tipos de dados

Se você já conhece, de alguma forma, a linguagem C++, já deve ter usado alguns tipos básicos de variáveis: int, float, double, bool etc – são chamados de tipos simples de dados. Vamos usar um exemplo inicial: digamos que desejamos representar uma casa. Vamos começar por examinar os diversos atributos de uma casa: número de quartos, o nome da rua, seu número (endereço), se tem ou não um jardim etc. Em C++, podemos representar a casa assim:

int      numero, quartos;
bool     jardim;

Isto já funciona bem para este exemplo, em particular, mas vamos supor que queremos representar várias casas. Vamos supor, ainda, que precisamos fazer o programa mais complexo do que ele está. E se usássemos nosso próprio tipo de dado para representar a casa em C++? Podemos fazê-lo com o uso de classes:

Classuda!

Até o momento, estamos usando nomes de objetos em português, para facilitar um pouco as coisas – desta forma fica fácil separarmos as palavras-chave da linguagem de programação dos nomes das variáveis. Mas isto irá mudar mais para frente.
Continuando com o nosso exemplo de casa, vejamos como é possível modelar uma casa usando uma classe em C++, tal como você pode ver no código abaixo:

class casa
{
public:
	int num, quartos; 
	bool quintal;
};

main()
{
	casa minha_casa;
	minha_casa.num=40; 
	minha_casa.quartos=8;
	minha_casa.quintal=1;
	return 0;
}

Vamos dar uma olhada no que este código faz.
Primeiro, declaramos uma nova classe e a chamamos “casa”.
Depois abrimos o processo de definição da classe, com as chaves ‘{‘. Em seguida, declaramos que todos os membros – tipos de dados pertencentes à classe, que seguem são públicos (falaremos mais disto depois).
Então, declaramos duas variáveis do tipo básico ‘int’ (inteiro). A próxima instrução declara que o membro “quintal” é do tipo bool (booleano – ou 1 ou 0).
Finalizamos a classe ao fechar as chaves ‘}’ e adicionando um ponto-e-vírgula ‘;’ ao final.
Em resumo, o que fizemos foi declarar um novo tipo de dados ou classe, chamada “casa”, que poderemos usar dentro do nosso programa.
Para fazer uso da classe casa, iniciamos a função main(), que é onde a execução do nosso programa começa e termina.
A primeira coisa feita foi declarar a variável minha_casa como sendo do tipo casa, que é a classe que definimos lá no início do programa. Agora, esta variável ganha novas dimensões.
A variável casa tem mais atributos do que apenas int ou float. De nossa classe de definição, demos à classe casa três variáveis: número, quartos e quintal. A variável recém declarada, minha_casa, tem todos estes atributos.
Na segunda linha da nossa função main(), definimos o número membro do objeto minha_casa para 40.
Da mesma maneira, definimos os valores dos outros três membros de dados de minha_casa, antes de fechar a função com o valor de retorno 0.
Neste ponto, você pode estar se perguntando o que pode haver de tão especial com estas três classes? Não seria mais simples usar o método não-orientado a objetos?
Nesta situação, em particular, o método de programação estruturada seria mais simples – principalmente por que estamos falando de um programa muito pequeno que faz muito pouca coisa. A situação muda de figura, contudo, se estivermos escrevendo um programa bem maior e mais complexo. Neste caso, as classes são mais do que apenas úteis, mas essenciais.

Continuação »

Uma introdução à Programação Orientada a Objetos em C++ (Parte I)

Introdução

C++_programming
Este “curto” artigo tem o objetivo de dar um pontapé inicial para quem deseja obter uma introdução à programação orientada a objetos. O uso da linguagem C++ é mais ou menos casual, aqui.
A abreviatura do conceito em inglês é OOP, enquanto em portuguẽs é comum usar POO. O problema é que poo, em inglês quer dizer cocô — motivo pelo qual espero que você entenda por que nós vamos evitar o seu uso.

O que é Programação Orientada a Objetos (OOP)

A OOP é, sem dúvida, uma das mais complexas técnicas de programação para se explicar. Na verdade, trata-se de mais do que “técnica”. Estamos falando de um novo método de abordar a programação, em si.
Como há uma variada gama de livros sobre o assunto, não faz sentido este artigo se aprofundar em todos os meandros filosóficos e em todas as implicações que envolvem a OOP. Para entender este conceito, acreditamos que seja importante para você entender primeiro como era a programação antes dele.
Naquele tempo, a estória era assim: um programa é uma sequência lógica de instruções a serem executadas pelo computador. Só. Nada animador, não?
Isto era o que se chama de programação estruturada.
Pois bem, no final dos anos 50, no MIT, o paradigma da orientação a objetos começava a ser gestado. Veio à tona há uns 20 anos e vem ganhando força nos dias atuais.
Na programação orientada a objetos se enfatiza os dados ou os ‘objetos’ manipulados e em como o programador os manipula. No paradigma anterior, números eram apenas endereços na memória; sequencias de bytes que não tinham significados relevantes.
Um programa deve oferecer meios de solucionar qualquer que seja o problema que você tenha a sua frente. Isto é feito olhando pros objetos que definem os problemas e usando funções que manipulam estes objetos.
Ainda que estes conceitos lhe pareçam confusos, eles não são tão necessários para que você possa fazer uso efetivo da OOP em seus programas. É programando que se aprende a programar, qualquer que seja a metodologia usada.

Continuação…

Hubs vs Switches vs Roteadores – diferenças

Introdução

Na infraestrutura da rede em que você está trabalhando, jogando, navegando (ou fazendo nada) você deve estar conectado a um hub, um switch ou um roteador (router, em inglês).Switch com luzes acesas, mostrando atividade.
Se você chegou aqui, é por que “bateu uma curiosidade” sobre o que é e como funciona basicamente cada equipamento destes.
Alguns conceitos dados e abordados neste artigo vão precisar de uma leitura mais aprofundada para serem melhor entendidos. Eu recomendo ler sobre o modelo OSI na Wikipedia, para adquirir mais conhecimento no assunto.

Hubs

Conhecidos também como repetidores, são dispositivos de rede que operam na camada física (layer 1) na conexão de outros dispositivos de rede para comunicação.

Hub Cisco 108T - Linux Network - MySQL
Clique na imagem para ver em tamanho maior – Hub Cisco 108T
  • Os hubs não processam o tráfego da camada 2 ou da camada 3. Não processam informações baseadas nos endereços MAC ou IP;
  • Tudo o que um hub faz é transferir dados a cada porta, excluindo-se aquela de onde os dados se originaram;
  • Hubs trabalham apenas no modo half duplex, o que significa que um dispositivo conectado a ele não pode enviar e receber dados simultaneamente. Envia dados em um momento e recebe dados em outro;
  • Se mais de um dispositivo enviar dados simultaneamente ocorre a colisão de dados;
  • Em caso de colisão, o hub rejeita os dados de todos os dispositivos e envia-lhes um sinal para enviar novamente;
  • Hubs têm propensão a colisões e, à medida em que vamos adicionando novos dispositivos e hubs à rede, as chances de ocorrerem colisões vão aumentando e o desempenho da rede, como consequência, vai caindo.

Switches

São aparelhos que operam na camada 2 (camada de enlace) no modelo OSI de comunicação.

Switches
Clique na imagem para ver em tamanho maior – switches
  • São também conhecidos como hubs inteligentes;
  • Os switches operam com os endereços de hardware dos dispositivos conectados para transferir dados entre estes;
  • O motivo de serem chamados hubs inteligentes é que montam uma tabela com os endereços de hardware e portas dos dispositivos conectados;
  • Assim que são ligados, agem de maneira limitada, tal como os hubs. Por isto são comparados a estes.

    Suponha que haja 3 dispositivos conectados a um determinado switch. Vamos chama-los, para simplificar, de dispositivo A, dispositivo B e dispositivo C.
    Agora, vamos imaginar que o sistema tenha sido reiniciado. Se o dispositivo A envia uma mensagem ao dispositivo B, então, tal como um hub, o switch vai remeter a mensagem a cada um dos outros dispositivos na rede &emdash; só que vai armazenar os endereços de hardware de cada dispositivo e a porta correspondente em uma tabela. Desta forma, na próxima vez em que houver um pacote destinado ao dispositivo A, o switch vai agir inteligentemente e enviá-lo apenas à porta correspondente, em vez de todas.

Assim, à medida em que a rede vai sendo usada, os endereços e as portas vão sendo “anotados” na tabela do switch e, após um certo tempo, já teremos um hub que envia inteligentemente os pacotes apenas pros destinatários certos;

  • Switches são comumente confundidos com pontes (bridges). Ainda que sejam similares, a maior diferença é que o switch usa um circuito de hardware especial chamado ASICs, que lhe permite direcionar os dados na velocidade máxima atribuída ao seu cabeamento (100 mbps, 1000mbps etc);
  • Diferente dos hubs, os switches têm a capacidade de transmitir dados em full duplex para cada dispositivo conectado;
  • Como os cabeçalhos (headers) dos protocolos da camada 2 não têm informação sobre a rede dos pacotes de dados, os switches não podem reenviar dados baseados nas redes. Por isto não são usados em grandes redes, que são subdivididas em várias sub-redes;
  • Com o uso do protocolo STP (Spanning Tree Protocol) os switches podem evitar loops dentro da rede &emdash; que “consiste no envio de um host com o pacote de IP de origem desconhecida ou falsa. Se Propaga nos roteadores e instala rotas erradas nas tabelas de roteamento”. (Wikipedia)

 

Roteadores

Os roteadores são os dispositivos, na rede, que operam na camada 3 (de rede ou Layer 3) do modelo OSI de comunicação.

    • Como os protocolos da camada de rede têm acesso aos endereços lógicos (endereços IP) os roteadores têm a capacidade de transmitir dados entre redes diferentes;
    • Podem ser comparados a switches de camada de rede;
    • Roteadores têm uma quantidade de recursos bem maior do que os switches;
    • Roteadores retém a tabela de rotas para a transmissão de dados;
    • Roteadores antigos eram lentos, se comparados aos switches. Isso se devia a que a consulta à tabela de roteamento levava um tempo consideravelmente alto, o que já não ocorre nos dias atuais, felizmente;
    • As operações de rede, nos roteadores atuais, são feitas em dispositivos com latência muito reduzida e, portanto, não são mais lentos do que os switches;
    • Roteadores geralmente têm menos portas do que switches;
    • Roteadores são comumente usados como elementos de transmissão de dados entre redes em WANs (Wide Area Networks).

Veja outros artigos relacionados a redes.

Como resolver problemas com o GPS no RunKeeper

O RunKeeper é um aplicativo (app) de monitoramento de suas atividades físicas. Similar a outros, como Runtastic, Nike+, Endomondo etc. As dicas dadas aqui podem ser aproveitadas, sem problemas, em outros apps desta mesma categoria.

O GPS é do seu celular

runkeeper-test-android-peteÉ importante entender que o software de monitoramento recebe informações do software que controla o hardware do GPS no seu aparelho. Aparelhos diferentes, têm softwares e hardwares relacionados ao Sistema de Posicionamento Global (GPS) diferentes. Alguns têm um conjunto de melhor qualidade, outros não.
Ainda assim, tudo pode e deve funcionar bem e nós vamos abordar alguns dos problemas mais comuns e que podem ser resolvidos de forma simples.

Ative o GPS primeiro

Ativar GPS no RunKeeperAntes de iniciar o aplicativo de monitoramento, ligue o GPS do seu aparelho. Nada impede que você faça o contrário. Mas é uma forma mais segura de permitir que o aplicativo se conecte ao hardware do sistema de posicionamento via satélite.

Tenha paciência

A conexão com o satélite demora um pouco. Esta demora pode variar em função do tipo de hardware que você tem instalado em seu smartphone. Ou seja, a marca e o modelo do seu aparelho pode influenciar.

Antecedência

Experimente ativar o GPS antes de sair de casa para ir treinar. Você pode ligar o RunKeeper também. Quando você chegar ao local do treino, tudo já estará sincronizado e funcionando – bastará tocar o botão “iniciar a atividade”.
Se você vai a pé até o local onde você pratica suas atividades, melhor ainda. Ao ar livre, durante a caminhada, o GPS vai funcionar melhor.

Concluindo

Mais sobre o RunKeeper

Evite ligar o GPS e o RunKeeper “em cima da hora”, pouco antes do exercício. Faça isto sempre com alguns minutos de antecedência à sua atividade.
Tenha um bom treino!