Programar em C++/Classes: diferenças entre revisões

[revisão pendente][revisão pendente]
Conteúdo apagado Conteúdo adicionado
m Foram revertidas as edições de 193.236.83.185 (disc) para a última revisão de 177.156.122.235
m <source> -> <syntaxhighlight> (phab:T237267)
 
Linha 16:
Observemos, por exemplo, o código abaixo:
 
<sourcesyntaxhighlight lang=cpp>
struct MyData
{ int n;
Linha 22:
float nReal;
};
</syntaxhighlight>
</source>
 
Esta declaração, bem conhecida de quem já está familiarizado com a linguagem C, cria um tipo de dado composto heterogêneo, que neste exemplo chamamos de MyData, o que acontece aqui é que os dados estão agrupados dentro desta estrutura, isto promove a possibilidade de manipulá-los em conjunto. Um dos problemas com esta estrutura é a presença de uma matriz de caracteres chamada "data", observe que a mesma tem um tamanho definido de 10 caracteres, imagine que em algum momento da execução do programa tentamos colocar um caractere na posição 11, ou qualquer posição fora da matriz, neste caso estamos colocando o referido dado em endereços inválidos para a operação que pretendemos realizar, ou seja, não há controle nenhum que assegure que o código não fará um acesso fora da área que pertença a matriz. Um acesso de memória a qualquer elemento da matriz acima da posição 9, fará com que invadamos dados na área onde a variável nReal está definida.
Linha 29:
 
Agora suponha que tenhamos como definir um modo para entrar e outro para ler dados da matriz:
<sourcesyntaxhighlight lang=cpp>
struct MyData
{ int n;
Linha 50:
}
};
</syntaxhighlight>
</source>
 
Agora temos assegurados métodos de inclusão e acesso a dados da matriz de caracteres, porém ainda existe um pequeno problema: Quem quiser o antigo método de acesso direto conseguirá facilmente, pois os elementos da estrutura estão acessíveis publicamente por padrão.
Linha 62:
As estruturas são bem parecidas com as classes, com uma pequena diferença, peguemos o caso da passagem de estruturas como argumentos de funções:
 
<sourcesyntaxhighlight lang=cpp>
#include <iostream>
#include <string>
Linha 101:
cout << "A altura da pessoa em milímetros é: " << pers.height << endl;
}
</syntaxhighlight>
</source>
 
 
Linha 134:
A solução é criar funções publicas, para ler de e escrever para as variáveis privadas:
 
<sourcesyntaxhighlight lang=cpp>
#include <iostream>
#include <string>
Linha 205:
cout << "Person's height in milimeters is: " << pers.getHeight() << endl;
}
</syntaxhighlight>
</source>
 
Mas perguntam: Por que é que nos demos ao trabalho de recorrer a membros privados em vez de fazer todos públicos?
Linha 222:
 
'''1º caso:'''
<sourcesyntaxhighlight lang=cpp>
class CRectangle
{
Linha 230:
int area (void);
} rect;
</syntaxhighlight>
</source>
 
No 2º caso, apresentado logo abaixo, podemos declarar objetos apenas quando precisarmos. Esta opção de declarar o objeto depois é a mais usada, pois na maioria das vezes temos o modelo dos objetos, a classe, declarada em um arquivo de cabeçalho enquanto que os objetos serão criados no resto do código fonte. Desta forma é mais usual criar as classes em cabeçalhos e depois declarar os objetos na parte do programa que for mais conveniente.
Linha 236:
 
'''2º caso:'''
<sourcesyntaxhighlight lang=cpp>
class CRectangle
{
Linha 249:
CRectangle rect;
}
</syntaxhighlight>
</source>
 
 
Linha 288:
Agora vamos mostrar que podemos ter funções membro apenas como protótipos e defini-las fora da classe. Para isso usamos o operador de definição de escopo '''::''' que permite definir o local do código onde um identificador existe, no formato: '''''ESCOPO::função''''' ou '''''ESCOPO::dado'''''. De maneira geral, quando declaramos identificadores dentro da classe podemos defini-los no escopo global referenciando estes pelo operador de escopo.
 
<sourcesyntaxhighlight lang=cpp>
// classes example
#include <iostream>
Linha 342:
return 0;
}
</syntaxhighlight>
</source>
 
area: 12
Linha 351:
Vejamos outro exemplo:
 
<sourcesyntaxhighlight lang=cpp>
class Dog
{
Linha 384:
cout << "BARK!!" << endl;
}
</syntaxhighlight>
</source>
 
Acima podemos ver um modo de declarar as funções apenas como protótipos, que ficam dentro da declaração da classe. Nesse contexto as funções são definidas fora da classe, usando-se o operador "'''::'''" para ligar a função à classe. Neste caso teremos as funções definidas e construídas no código das mesmas, enquanto que o modelo da classe poderá permanecer em um arquivo cabeçalho, o que possibilita incluí-lo em qualquer arquivo de códigos fontes do programa.
Linha 409:
A primeira versão então seria:
 
<sourcesyntaxhighlight lang=cpp>
class Image {
public:
Linha 435:
double clipIntensity(double brightness);
};
</syntaxhighlight>
</source>
 
== Especificadores de acesso ==
Linha 480:
Podemos criar construtores facilmente, através das características que os distinguem das funções membro convencionais. Ou seja, definimos uma função membro que possua o mesmo nome da classe, não tenha tipo de retorno e a declaramos como pública para que possa ser acessada por quem queira instanciar objetos. Vejamos como definir um construtor:
 
<sourcesyntaxhighlight lang="cpp">
 
class Caneta
Linha 494:
volume = v;
}
</syntaxhighlight>
</source>
 
Construtores podem iniciar os membros da classe de uma forma simplificada. Este formato é usado sempre que o construtor tem dados básicos que podem ser iniciados antes do resto da construção da estrutura do objeto. Podemos iniciar os dados do objeto declarando-o desta forma:
 
<sourcesyntaxhighlight lang="cpp">
 
class Caneta
Linha 509:
}
};
</syntaxhighlight>
</source>
 
Para fazê-lo, como vemos no código, basta listar as variáveis membro em uma sequência depois da declaração do nome do construtor e de um sinal de dois pontos ":". Iniciamos uma lista de membros, com o valor a ser atribuído entre parênteses depois de cada um, separando-os por vírgulas.
Linha 526:
Façamos a classe Dog com o construtor e o destrutor.
 
<sourcesyntaxhighlight lang=cpp>
class Dog
{
Linha 553:
cout << "Dog Destructor Called" << endl;
}
</syntaxhighlight>
</source>
 
Repare que:
Linha 567:
Em algumas situações a cópia de um objeto não é satisfatória, para ver isso vamos ver a classe employee, abaixo:
 
<sourcesyntaxhighlight lang=cpp>
#include <iostream>
#include <string.h>
Linha 602:
return 0;
}
</syntaxhighlight>
</source>
 
A função strlen retorna o tamanho da string passada pelo constructor.
Linha 613:
Agora imagine que o john é promovido:
 
<sourcesyntaxhighlight lang=cpp>
int main()
{
Linha 628:
return 0;
}
</syntaxhighlight>
</source>
 
Este programa contém um bug sério e morre com uma exceção quando é executado. O problema é que o construtor que está sendo usado é para criar um objeto “manager", mas ele copia o endereço no ponteiro _name em "manager".
Linha 638:
Para criar o construtor basta definí-lo na classe:
 
<sourcesyntaxhighlight lang=cpp>
 
class Employee
Linha 659:
}
 
</syntaxhighlight>
</source>
 
Agora temos um construtor que pode fazer a cópia da forma correta. Neste novo construtor alocamos uma cadeia de caracteres para copiar o conteúdo da original no objeto a ser copiado e copiamos o conteúdo para o novo objeto. Assim, teremos objetos distintos, cada um com seu próprio conteúdo.