Mais Sobre Construtores em C++
Dessa vez não vou falar muito mas sim exemplifiar um dos features (hehehe) do C++ que são as diferentes maneiras de “construir” um objeto. O código está todo em um arquivo para facilidar a visualização aqui no blog.
Eis o código:
#include <iostream>
using std::cout;
class Teste
{
char tipo;
int valorInt;
char valorChar;
double valorDouble;
public:
Teste(const Teste& t)
{
tipo = t.getTipo();
valorInt = t.getValorInt();
valorChar = t.getValorChar();
valorDouble = t.getValorDouble();
}
Teste(char v)
{
tipo = 'c';
valorInt = 0;
valorChar = v;
valorDouble = 0;
}
Teste(int v)
{
tipo = 'i';
valorInt = v;
valorChar = 0;
valorDouble = 0;
}
Teste(double v)
{
tipo = 'd';
valorInt = 0;
valorChar = 0;
valorDouble = v;
}
char getValorChar() const { return valorChar; };
int getValorInt() const { return valorInt; };
double getValorDouble() const { return valorDouble; };
char getTipo() const { return tipo; };
void imprimeValor() const
{
if (tipo == 'c') cout << valorChar;
else if (tipo == 'd') cout << valorDouble;
else cout << valorInt;
cout << '\n';
};
~Teste() {};
};
int main()
{
Teste a = 1;
Teste b = 'm';
Teste c = 3.1417;
Teste d = (Teste)2;
Teste e = a;
Teste f(100);
Teste g = static_cast<Teste>('a');
a.imprimeValor();
b.imprimeValor();
c.imprimeValor();
d.imprimeValor();
e.imprimeValor();
f.imprimeValor();
g.imprimeValor();
}
E a saída correspondente:
1
m
3.1417
2
1
100
a
Internamente todas as formas de construir o objeto fazem a mesma coisa: procuram um construtor que espere aquele tipo de parâmetro e cria um objeto (no caso Teste).
Claro que isso pode ser modificado se sobrecarregarmos o operator=, operator() (unário) ou usar a keyword explicit na declaração dos construtores.
O que são enums e como utilizá-los melhor em C++

O que são os enums (C e C++)
Um enum (enumeração) é um tipo definido pelo usuário (programador) que consiste em constantes do tipo int nomeadas.
Um jeito tradicional de se declarar constantes em C e C++ é o seguinte:
#define BRASIL 0 #define ITALIA 1 #define PORTUGAL 2 #define ALEMANHA 3
E eis a maneira de fazer o mesmo utilizando enums:
enum
{
BRASIL,
ITALIA,
PORTUGAL,
ALEMANHA
};
Pode-se, alternativamente, criar um tipo para seu enum:
enum Paises
{
BRASIL,
ITALIA,
PORTUGAL,
ALEMANHA
};
E declarar uma variável desse tipo com:
Paises pais; //C++ apenas enum Paises pais; //C e C++
Num enum igual a esses acima, a primeira constante recebe o valor 0 e as subsequentes recebem o valor da constante anterior mais 1. Ou seja, BRASIL é 0, ITALIA é 1, PORTUGAL é 2 e ALEMANHA é 3.
Podemos também atribuir valores manualmente às constantes como em:
enum Paises
{
BRASIL = 2,
ITALIA, //ITALIA é igual a 3 (2 + 1)
PORTUGAL = 1,
ALEMANHA //ALEMANHA é igual a 2 (1 + 1)
};
Como podemos perceber no exemplo anterior, a mesma regra se aplica para os enums com valores manuais, o que não tiver um valor explicitamente inserido receberá o valor do anterior somado em 1. Percebemos também que podem haver constantes com o mesmo valor (BRASIL == ALEMANHA == 2).
Conversão
A conversão de uma constante de um enum para um inteiro por exemplo é feita automaticamente. Já o contrário não deve ser permitido pelo compilador.
enum Paises
{
BRASIL,
ARGENTINA,
VENEZUELA
};
...
int inteiro = VENEZUELA + 2; //4
Paises pais = 3; //ERRO
Uma melhor maneira de usar enums em C++
Veja o exemplo:
enum Paises
{
BRASIL,
ITALIA,
ALEMANHA
};
enum Uvas
{
RUBI,
ITALIA,
UMOUTROTIPODEUVA
};
Isso irá ocasionar um erro porque ITALIA já foi definido. A saida do meu compilador (g++ 4.3.2) foi a seguinte:
murilo@blacksheep:~/$ g++ enums.cpp
enums.cpp:14: error: conflicting declaration ‘ITALIA’
enums.cpp:8: error: ‘ITALIA’ has a previous declaration as ‘Paises ITALIA’
Mas e agora?? Eu quero ter dois enums diferentes que representam coisas diferentes mas que podem ter a mesma constante. Como?
A resposta é namespaces!
Em C++ podemos declarar nossos enums dentro de namespaces e assim termos as constantes em espaços de nomes diferentes. Nada de conflito agora hein g++!!!
namespace Paises
{
enum
{
BRASIL,
ITALIA,
ALEMANHA
};
}
namespace Uvas
{
enum
{
RUBI,
ITALIA,
UMOUTROTIPODEUVA
};
}
//*...*//
//Modo de uso:
std::cout << Uvas::ITALIA;
std::cout << Paises::ITALIA;
É isso aí galera, até a próxima.
Como implementar facilmente getters e setters em C++
Se você é como eu que odeia ficar digitando dois métodos para cada atributo que você cria em sua classe, seus problemas acabaram.
Trata-se de uma macro feita através de um #define mesmo que facilita muito a vida dos programadores OO em C++.
Vejamos a macro:
#define declare(type, name) \
private: type _##name; \
public: \
void set##name(const type& var) \
{\
_##name = var;\
}\
\
type get##name() \
{\
return _##name; \
}\
Define para fácil alocação de matrizes em C++
Houve uma questão na comunidade C e C++ Brasil no Orkut sobre alocação de matrizes em C++ e resolvi fazer algo para facilitar a alocação delas.
Nada de algo complicado, trata-se do simples #define abaixo:
#define matalloc(t, x, y, z) \ x = new t*[y]; \ for (int i = 0; i < y; i++) x[i] = new t[z];
Onde:
- t é o tipo dos elementos da matriz;
- x é a variável (ponteiro pra ponteiro) que receberá a matriz;
- y é a quantidade de linhas que a matriz terá;
- z é a quantidade de colunas.
Uso:
#include
using namespace std;
#define matalloc(t, x, y, z) \
x = new t*[y]; \
for (int i = 0; i < y; i++) x[i] = new t[z];
int main()
{
int** x;
matalloc(int, x, 3, 3);
x[0][0] = 2;
x[1][2] = 4;
cout << x[0][0] << " " << x[1][2] << endl;
}
Exemplo:
Comparação de desempenho: std::vector vs Array
Comparação entre os códigos assembly gerados para operações de indexação básica, dereferenciação eincremento em std::vectors e arrays/ponteiros.
O código assembly foi gerado pelo gcc 4.1.0 chamado com g++ -03 -S em uma máquina x86_64-suse-linux.
#include
struct S
{
int padding;
std::vector v< int >; //nosso vector
int * p; //nosso ponteiro
std::vector< int >::iterator i; //iterador do vector
};
int indexar_ponteiro(S & s) { return s.p[3]; }
// movq 32(%rdi), %rax
// movl 12(%rax), %eax
// ret
int indexar_vector(S & s) { return s.v[3]; }
// movq 8(%rdi), %rax
// movl 12(%rax), %eax
// ret
// Conclusão: Indexar um std::vector é a mesma coisa de indexar um ponteiro.
int deref_ponteiro(S & s) { return *s.p; }
// movq 32(%rdi), %rax
// movl (%rax), %eax
// ret
int deref_iterador(S & s) { return *s.i; }
// movq 40(%rdi), %rax
// movl (%rax), %eax
// ret
// Conclusão: Dereferenciar um std::vector é a mesma coisa de dereferenciar um ponteiro.
void incrementar_ponteiro(S & s) { ++s.p; }
// addq $4, 32(%rdi)
// ret
void incrementar_iterador(S & s) { ++s.i; }
// addq $4, 40(%rdi)
// ret
// Conclusão: Incrementar um iterador de std::vector é a mesma coisa de incrementar um ponteiro.
Ou seja, além das facilidades do std::vector, algumas operações básicas tem o mesmo custo tanto com std::vector quanto um array/ponteiro.
Surpreso?
Smart Pointers: Os Ponteiros Espertos do C++
E aí pessoal, como prometido, vou falar sobre Smart Pointers em C++.
Neste post irei abordar smart pointers, o que são, como funcionam e para que são usados, além de mostrar um exemplo de implementação de smart pointers.
1. Introdução:
O que são Smart Pointers?
Smart pointers são implementações feitas para facilitar e ajudar no manuseamento de ponteiros. Para serem mais “inteligentes” que os ponteiros normais, os smart pointers precisam fazer coisas que os ponteiros normais não fazem. Leia o resto deste post »
Ranking TIOBE de Linguagens de Programação Nov/2008
Saiu o índice TIOBE de novembro.
O índice TIOBE indica a popularidade das linguagens de programação. O índice é atualizado uma vez por mês. Os mecanismos de busca populares Google, MSN, Yahoo! e YouTube são usados para obter a classificação. Observe que o índice TIOBE não indica qual é a melhor linguagem de programação ou a linguagem que tem maior número de linhas de código escrito.
| Posição Nov 2008 |
Posição Nov 2007 |
Variação | Linguagem | Nov 2008 | Variação Nov 2007 |
Status |
|---|---|---|---|---|---|---|
| 1 | 1 | ![]() |
Java | 20.299% | -0.24% | A |
| 2 | 2 | ![]() |
C | 15.276% | +1.31% | A |
| 3 | 4 | ![]() |
C++ | 10.357% | +1.61% | A |
| 4 | 3 | ![]() |
(Visual) Basic | 9.270% | -0.96% | A |
| 5 | 5 | ![]() |
PHP | 8.940% | +0.25% | A |
| 6 | 7 | ![]() |
Python | 5.140% | +0.91% | A |
| 7 | 8 | ![]() |
C# | 4.026% | +0.11% | A |
| 8 | 11 | ![]() ![]() ![]() |
Delphi | 4.006% | +1.55% | A |
| 9 | 6 | ![]() ![]() ![]() |
Perl | 3.876% | -0.86% | A |
| 10 | 10 | ![]() |
JavaScript | 2.925% | 0.00% | A |
| 11 | 9 | ![]() ![]() |
Ruby | 2.870% | -0.21% | A |
| 12 | 12 | ![]() |
D | 1.442% | -0.26% | A |
| 13 | 13 | ![]() |
PL/SQL | 0.939% | -0.24% | A |
| 14 | 14 | ![]() |
SAS | 0.729% | -0.40% | A– |
| 15 | 18 | ![]() ![]() ![]() |
ABAP | 0.570% | -0.08% | B |
| 16 | 19 | ![]() ![]() ![]() |
Pascal | 0.511% | -0.13% | B |
| 17 | 17 | ![]() |
COBOL | 0.510% | -0.20% | B |
| 18 | 25 | ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
ActionScript | 0.506% | +0.04% | B |
| 19 | 23 | ![]() ![]() ![]() ![]() |
Logo | 0.489% | -0.04% | B |
| 20 | 16 | ![]() ![]() ![]() ![]() |
Lua | 0.473% | -0.27% | B |
Fonte: http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
Troquei o Ubuntu 8.10 pelo openSUSE 11!
Este post é só pra dizer o tanto que fiquei magoado com o Ubuntu 8.10 e que resolvi mudar.
Fui usuário do Ubuntu um bom tempo. Desde o 6.10 eu o usava e abusava dele. Só que de lá pra cá algumas coisas me deixaram “cabreiro” com o Ubuntu.
A primeira coisa é o péssimo suporte ao plugin do flash. Muito lento, trava demais, fecha.
A segunda coisa é o baixo desempenho. Uma lerdeza! O sistema ficava muito instável com algumas aplicações.
A terceira reclamação é sobre a atualização. Lembro-me que quando fui atualizar o Ubuntu do 7.10 para o 8.04, nossa, quanto sofrimento, e agora ocorreu o mesmo ao atualizar do 8.04 para o 8.10. O sistema inicia com som só quando quer, o X às vezes dá “tilt”, não tem mais suporte à algumas placas de vídeo que antes tinha (inclusive a minha dinossaura NVidia GeForce MX 440). Pra mim foi a gota d’água!
Resolví respirar novos ares.Cheguei a baixar o Debian mas, por influência do Fred (meu colega de faculdade) que por coincidência estava com o DVD do openSUSE no dia e hora certa, acabei instalando o openSUSE no notebook e baixei o LiveCD do openSUSE para meu PC desktop (o blacksheep
) porque minha unidade de DVD estragou.
A instalação do openSUSE foi tranqüila. Com uma interface bastante amigável e agradável, a instalação foi muito simples. Se não fosse pelo fato de eu ter escolhido o tamanho de Swap e algumas opções mais “avançadas”, eu diria que qualquer pessoa com o mínimo de domínio sobre o computador poderia ter instalado.

Instalação do openSUSE: Escolha do Gerenciador de Janelas
Escolhi o KDE4 (foi uma dor abandonar o GNOME de tanto tempo) para ver como é que é. Admito que gostei! Bastante leve com muitos recursos e bem bonito.
Curti bastante o YaST2 que torna a configuração do openSUSE bem simples. Gostei também do 1-Click Install que é uma maneira fácil de instalar software no openSUSE.
Por enquanto não tive problemas com drivers de hardware. O SO reconheceu tudo direitinho.
Agora é só esperar… O tempo irá dizer se foi uma boa escolha ou não.
Regards!
Linguagens de programação – C++ – Direito de defesa
Um dia desses passeando por blogs ví um post que me chamou a atenção. O título é Linguagens de programação – C++ e, claro, chamou minha atenção, não apenas por causa do post assim com também por causa dos comentários sobre o post.
O objetivo desse post não é gerar um flame, até porque não atacarei nenhuma linguagem, só dissertarei sobre fatos.
Nova versão do Ubuntu chegando!
É isso aí galera! Falta pouco!
O Ubuntu 8.10 está chegando e promete várias melhorias. Entre elas estão o GNOME 2.24 o Xorg 7.4 e a versão 2.6.27 do kernel do Linux.
Existe uma versão beta para downloads disponível no ubuntu.com.
Existe uma script feito para a contagem regressiva para o lançamento do Ubuntu 8.10, que será no próximo dia 30, feito em javascript e como o WordPress não deixa usar JS, resolvi implementar esse script em PHP para colocá-lo aqui. Ele pode ser acessado por essa URL.



