Diferenças entre edições de "Programar em C++/Classes"

270 bytes adicionados ,  15h38min de 16 de abril de 2020
m
<source> -> <syntaxhighlight> (phab:T237267)
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))
 
Observemos, por exemplo, o código abaixo:
 
<sourcesyntaxhighlight lang=cpp>
struct MyData
{ int n;
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.
 
Agora suponha que tenhamos como definir um modo para entrar e outro para ler dados da matriz:
<sourcesyntaxhighlight lang=cpp>
struct MyData
{ int n;
}
};
</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.
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>
cout << "A altura da pessoa em milímetros é: " << pers.height << endl;
}
</syntaxhighlight>
</source>
 
 
A solução é criar funções publicas, para ler de e escrever para as variáveis privadas:
 
<sourcesyntaxhighlight lang=cpp>
#include <iostream>
#include <string>
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?
 
'''1º caso:'''
<sourcesyntaxhighlight lang=cpp>
class CRectangle
{
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.
 
'''2º caso:'''
<sourcesyntaxhighlight lang=cpp>
class CRectangle
{
CRectangle rect;
}
</syntaxhighlight>
</source>
 
 
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>
return 0;
}
</syntaxhighlight>
</source>
 
area: 12
Vejamos outro exemplo:
 
<sourcesyntaxhighlight lang=cpp>
class Dog
{
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.
A primeira versão então seria:
 
<sourcesyntaxhighlight lang=cpp>
class Image {
public:
double clipIntensity(double brightness);
};
</syntaxhighlight>
</source>
 
== Especificadores de acesso ==
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
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
}
};
</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.
Façamos a classe Dog com o construtor e o destrutor.
 
<sourcesyntaxhighlight lang=cpp>
class Dog
{
cout << "Dog Destructor Called" << endl;
}
</syntaxhighlight>
</source>
 
Repare que:
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>
return 0;
}
</syntaxhighlight>
</source>
 
A função strlen retorna o tamanho da string passada pelo constructor.
Agora imagine que o john é promovido:
 
<sourcesyntaxhighlight lang=cpp>
int main()
{
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".
Para criar o construtor basta definí-lo na classe:
 
<sourcesyntaxhighlight lang=cpp>
 
class Employee
}
 
</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.
251

edições