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

24 242 bytes adicionados ,  22h59min de 20 de dezembro de 2009
m
mexendo um pouco no texto, conceitos gerais (link), fr:, es:
m (mexendo um pouco no texto, conceitos gerais (link), fr:, es:)
== Classes ==
 
Existem duas categorias de tipos de dados usuais em C++, são classificados como '''tipos básicos''' e '''tipos definidos pelo programador''', assim como na linguagem C, podemos definir dados compostos por associações dos tipos básicos, estes tipos são chamados de '''structs'''. C++ traz uma nova representação de dados, muito semelhante na forma às structs, porém diferentes na forma conceitual, a palavra chave '''class''', pode ser usada para criar tipos de '''objetos'''.
 
Assim como na linguagem C, podemos definir dados compostos por associações dos tipos básicos, estes tipos são chamados de '''structs'''. C++ traz uma nova representação de dados, muito semelhante na forma às structs, porém diferentes na forma conceitual: a palavra chave '''class''', que é usada para criar uma classe de objetos mais rica que as ''structs''. Uma variável cujo tipo seja uma classe é chamada de um '''objetos'''.
Antes de prosseguirmos, vejamos um pouco sobre o conceito por tras do uso de objetos... Um objeto é entendido como uma entidade de dados dentro da memória que, basicamente, deve ser responsável por seu conteúdo, ou seja, um objeto deve ser capaz gerenciar seu conteúdo autonomamente, ou prover meios de outras entidades de código fazê-lo de forma segura.
 
Antes de prosseguirmos, vejamos um pouco sobre o conceito por trás do uso de objetos. Um objeto é entendido como uma entidade de dados dentro da memória que, basicamente, deve ser responsável por seu conteúdo, ou seja, um objeto deve ser capaz de gerenciar seu conteúdo autonomamente, ou prover meios de outras entidades de código fazê-lo de forma segura.
 
=== Origem (atributos) ===
=== Conceituação ===
 
O problema da visbilidadevisibilidade pública dos dados em uma estrutura pode ser resolvido com um dos conceitos de objetos, o encapsulamento. Encapsular os dados, significa reservar o acesso a funções que estejam dentro de um grupo restrito, especializado para tais operações de manipulação destes dados. Uma das vantagens deste procedimento é que o código adquire um formato mais modularizado, onde os processos tornam-se claramente distintos, caso tenhamos que analisar o código, cada procedimento estará restrito a partes definidas para cada operação.
 
== Declarando classes ==
 
Nos temos 2 pointers ambos contendo o mesmo endereço. Imagine que agora um novo empregado é contratado. quando o nome for atualizado, não apenas iremos alterar o nome do empregado mas também do gerente. Finalmente, quando os objetos deixarem de ser usados e o destrutor da classe fizer a liberação de espaço na memória tentará liberar duas vezes para o mesmo endereço, provocando um erro no sistema de alocação dinâmica de memória, o que forçará o sistema operacional a eliminar o programa da memória.
 
== Ver também ==
* [[Programação orientada a objetos/Classes e Objetos]] - conceitos teóricos
 
{{indentar/fim}}
 
[[Categoria:Programar em C++|Classes]]
 
Texto a negritoTexto em itálicoLigação internaLigação externa (lembre-se do prefixo http://)Secção de nível 2Ficheiro embutidoLigação para ficheiroFórmula matemática (LaTeX)Ignorar formatação wikiA sua assinatura, com hora e dataLinha horizontal (utilize moderadamente)2009122022475220091214183517d41d8cd98f00b204e9800998ecf8427e{{Nav2|[[Imagem:C++ Book Cover.png|30px]]|[[../Manipulando strings/]]|[[../Friend/]]}}
{{reciclagem}}
 
{{indentar}}
 
== Classes ==
 
Existem duas categorias de tipos de dados usuais em C++, são classificados como '''tipos básicos''' e '''tipos definidos pelo programador'''.
 
Assim como na linguagem C, podemos definir dados compostos por associações dos tipos básicos, estes tipos são chamados de '''structs'''. C++ traz uma nova representação de dados, muito semelhante na forma às structs, porém diferentes na forma conceitual: a palavra chave '''class''', que é usada para criar uma classe de objetos mais rica que as ''structs''. Uma variável cujo tipo seja uma classe é chamada de um '''objetos'''.
 
Antes de prosseguirmos, vejamos um pouco sobre o conceito por trás do uso de objetos. Um objeto é entendido como uma entidade de dados dentro da memória que, basicamente, deve ser responsável por seu conteúdo, ou seja, um objeto deve ser capaz de gerenciar seu conteúdo autonomamente, ou prover meios de outras entidades de código fazê-lo de forma segura.
 
=== Origem (atributos) ===
 
Observemos, por exemplo, o código abaixo:
 
<source lang=cpp>
struct MyData
{ int n;
char data[10];
float nReal;
};
</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.
 
=== Funções membro (Métodos) ===
 
Agora suponha que tenhamos como definir um modo para entrar e outro para ler dados da matriz:
<source lang=cpp>
struct MyData
{ int n;
char data[10];
float nReal;
 
bool write_data(int pos, char c)
{ if (pos >= 0 && pos < 10)
{ data[pos]=c;
return true;
}
return false;
}
 
char read_data(int pos)
{ if (pos >= 0 && pos < 10)
{ return data[pos];
}
return '\0';
}
};
</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 estutura estão acessíveis publicamente por padrão.
 
=== Conceituação ===
 
O problema da visibilidade pública dos dados em uma estrutura pode ser resolvido com um dos conceitos de objetos, o encapsulamento. Encapsular os dados, significa reservar o acesso a funções que estejam dentro de um grupo restrito, especializado para tais operações de manipulação destes dados. Uma das vantagens deste procedimento é que o código adquire um formato mais modularizado, onde os processos tornam-se claramente distintos, caso tenhamos que analisar o código, cada procedimento estará restrito a partes definidas para cada operação.
 
== Declarando classes ==
 
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:
 
<source lang=cpp>
#include <iostream>
#include <string>
 
using namespace std;
 
class Person
{
string name;
int height;
};
 
void setValues(Person&);
void getValues(const Person&);
 
int main ()
{
Person p1;
setValues(p1);
cout << "Informando dados sobre a pessoa:\n";
cout << "================================\n";
getValues(p1);
#ifdef WIN32
system ("pause");
#endif
return 0;
}
 
void setValues(Person& pers)
{
cout << "Informe o nome da pessoa: ";
getline(cin, pers.name);
cout << "Informe a altura em milímetros: ";
cin >> pers.height;
cin.ignore();
}
 
void getValues(const Person& pers)
{
cout << "Nome da pessoa: " << pers.name << endl;
cout << "A altura da pessoa em milímetros é: " << pers.height << endl;
}
</source>
 
 
* Mudamos o identificador de '''struct''' para '''class'''
* Mas se tentarmos compilar o programa isto vai causar erros de compilação, porque agora temos variáveis membro que são privadas por padrão, estas não são vistas por funções fora da classe.
 
 
Dentro de uma classe podemos definir diversos modos de visibilidade de variáveis e funções.
 
As modalidades podem ser:
*'''private''' (só podem ser acessados por membros da mesma classe)
*'''public''' (pode ser acessadas fora do objeto, onde este estiver definido)
*'''protected''' (deixemos esta para quando falarmos em classes derivadas, pois depende deste conceito).
 
Ora, como as funções getValues e setValues não são membros da classe Person, tal como o construtor Person, não conseguem acessar as variáveis "name" e "height".
 
Representação
{|{{prettytable}}
!
{| {{prettytable}}
| Class Person
| private
|-
|
|string name
|-
|
|Int height
|}
p1
|}
 
A solução é criar funções publicas, para ler de e escrever para as variáveis privadas:
 
<source lang=cpp>
#include <iostream>
#include <string>
using namespace std;
 
class Person
{
private:
string name;
int height;
public:
string getName() const;
void setName(string);
int getHeight() const;
void setHeight(int);
};
 
string Person::getName() const
{ return name; }
 
void Person::setName(string s)
{
if (s.length() == 0)
name = "No name assigned";
else
name = s;
}
 
int Person::getHeight() const
{ return height; }
 
void Person::setHeight(int h)
{
if (h < 0)
height = 0;
else
height = h;
}
 
void setValues(Person&);
void getValues(const Person&);
 
int main ()
{
Person p1;
setValues(p1);
cout << "Outputting person data\n";
cout << "======================\n";
getValues(p1);
return 0;
}
 
void setValues(Person& pers)
{
string str;
int h;
cout << "Enter person's name: ";
getline(cin,str);
pers.setName(str);
cout << "Enter height in milimeters: ";
cin >> h;
cin.ignore();
pers.setHeight(h);
}
 
void getValues(const Person& pers)
{
cout << "Person's name: " << pers.getName() << endl;
cout << "Person's height in milimeters is: " << pers.getHeight() << endl;
}
</source>
 
Mas perguntam: Por que é que nos demos ao trabalho de recorrer a membros privados em vez de fazer todos públicos?
Quando tínhamos uma estrutura no lugar de uma classe, não havia nada que impedisse a colocação de valores inválidos, por isso poderíamos ter valores vazios para a string e valores negativos para a variável "height".
 
Agora que "Person" é uma classe, as funções membro podem realizar a validação dos dados antes antes da atribuição de valores nas variáveis. Poderíamos fazer com que a função setName verificasse se a entrada na string seria vazia e caso fosse, colocaria um valor padrão como: “sem nome”. similarmente poderíamos ter "setHeight" para verificar se seriam colocados valores de entrada negativos e caso fossem, colocaria zero, ou não tomaria nenhuma ação.
 
Todas estas características demonstram o conceito de encapsulamento. A sua finalidade é de tornar o código mais modularizado, restringindo o escopo de análise a partes bem delimitadas dos programas. Devido a este conceito podemos contar com códigos mais fáceis de analisar e fazer manutenção.
 
== Instanciando objetos ==
 
Instanciação de objetos é o processo de criar a estrutura lógica dos mesmos na memória.Isto ocorre quando declaramos os objetos, pois neste momento todo o processo de construção dos mesmos é efetivado. Assim, toda vez que declaramos um objeto estamos instanciando-o.
 
Podemos declarar os objetos logo após definir a classe conforme podemos ver no 1º caso logo abaixo. Neste caso teremos a variável rect criada como um objeto conforme estabelecido pelo modelo definido pela palavra chave '''class'''. Este tipo de declaração é mais usual para objetos criados globalmente, pois a inclusão desta declaração no cabeçalho pode fazer com que vários objetos sejam criados com o mesmo nome quando o cabeçalho é invocado de vários arquivos. Portanto, é mais prudente usar esta opção quando a declaração está no arquivo fonte e não no cabeçalho.
 
 
'''1º caso:'''
<source lang=cpp>
class CRectangle
{
int x, y;
public:
void set_values (int,int);
int area (void);
} rect;
</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:'''
<source lang=cpp>
class CRectangle
{
int x, y;
public:
void set_values (int,int);
int area (void);
};
 
int main()
{
CRectangle rect;
}
</source>
 
 
Em ambos os casos temos
 
{| {{prettytable}}
!
{| {{prettytable}}
! CRectangle
! Private
! public
|-
|
| int x
|
|-
|
| int y
|
|-
|
|
| void set_values (int,int);
|-
|
|
| int area (void);
|}
rect
|}
 
Podemos, então, entender os objetos como blocos de dados que têm propriedades (variáveis) e que podem fazer algo (métodos). Então, criamos todas as funcionalidades que precisamos que a classe forneça aos programas, fazendo os testes necessários para assegurar sua consistência e establidade. Sempre que precisemos utilizar os objetos só temos que instanciá-los (declará-los), e não precisamos nos preocupar como eles funcionam internamente, uma vez que os desenhamos adequadamente.
 
Para entendermos melhor este conceito podemos fazer uma analogia. Consideremos um objeto resistência: sabemos que temos de usá-lo e que ela deve ter certas características, então teremos o seu valor em Ohms, sua potência máxima, tolerância, entre outras, e teremos uma função que nos dará a corrente que passa por ela quando lhe aplicamos uma tensão elétrica. Não precisamos saber de que é que ela é feita, ou como estas características internas a faz funcionar, basta-nos receber os resultados.
 
Vejamos o exemplo:
 
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 definí-los no escopo global referenciando estes pelo operador de escopo.
 
<source lang=cpp>
// classes example
#include <iostream>
using namespace std;
 
class CRectangle
{
int x, y;
public:
void set_values (int,int);
int area () {return (x*y);}
};
 
void CRectangle::set_values (int a, int b)
{
x = a;
y = b;
}
 
//repare no “::” que pemite-nos definir a função membro da classe CRectangle fora da classe
 
int main ()
{
CRectangle rect; //definimos objecto de classe
rect.set_values (3,4); //objecto-membro
cout << "area: " << rect.area();
system (“pause”);
return 0;
}
 
// classes example
#include <iostream>
using namespace std;
 
class CRectangle
{
int x, y;
public:
void set_values (int a,int b)
{
x = a;
y = b;
}
int area () {return (x*y);}
};
 
int main ()
{
CRectangle rect; //definimos objecto de classe
rect.set_values (3,4); //objecto-membro
cout << "area: " << rect.area();
system ("pause");
return 0;
}
</source>
 
area: 12
 
O exemplo anterior explora a característica de toda figura geométrica fechada, que possui uma área interna. Observe que este modo de definir a classe coloca o cálculo da área dentro da definição da mesma. Este modo faz com que o código seja apenas um modelo, a função de cálculo da área não será criada se não for usada durante o escrita do resto do programa.
 
 
Vejamos outro exemplo:
 
<source lang=cpp>
class Dog
{
public:
void setAge(int age);
int getAge();
void setWeight(int weight);
int getWeight();
void speak();
private:
int age;
int weight;
};
void Dog::setAge(int age)
{
this->age = age;
}
int Dog::getAge()
{
return age;
}
void Dog::setWeight(int weight)
{
this->weight = weight;
}
int Dog::getWeight()
{
return weight;
}
void Dog::speak()
{
cout << "BARK!!" << endl;
}
</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.
 
== Definição de classes ==
 
Usa-se a palavra '''class''' para criar uma classe, seguindo-se depois o nome que se queira dar-lhe e finalmente a definição da mesma entre chaves.
 
A definição contém:
* os dados ( propriedades );
* os métodos (as funções membro)
 
Vamos acompanhar com um exemplo:
Vamos fazer o desenho de uma classe chamada de “Image” que será usada para guardar e manipular uma imagem.
 
Primeiro perguntamos o que é necessário para guardar uma imagem e depois que tipo de manipulações é que necessitamos.
 
Então a imagem tem de largura e altura medida em pixeis 400 por 300. Cada pixel tem as propriedades de cor e imagem. a cor é composta por 3 cores separadas vermelho, azul e verde, numa escala de 0 a <math>2^{64}</math>.
Portanto vamos necessitar de membros para guardar estas informações
 
Agora planejemos os métodos. vamos primeiramente assumir que temos a restrição de <= 400 pixeis, e estes valores serão feitos pelo constructor na criação do objecto. nós não precisamos dos métodos para estipular a altura e largura, mas vamos precisar para obter e ler os valores.
Esta estratégia também nos ajudará a manter os valores de um determinado pixel e a sua localização.
 
A primeira versão então seria:
 
<source lang=cpp>
class Image {
public:
int getWidth();
int getHeight();
void setX(int x);
int getX();
void setY(int y);
int getY();
void setRed(double red);
double getRed();
void setBlue(double blue);
double getBlue();
void setGreen(double green);
double getGreen();
private:
int _width;
int _height;
int _x;
int _y;
double _red[400][400];
double _blue[400][400];
double _green[400][400];
boolean isWithinSize(int s);
double clipIntensity(double brightness);
};
</source>
 
== Especificadores de acesso ==
 
*Temos as palavras reservadas '''private''' e '''public''' – são os chamados especificadores de acesso.
**'''private''' – Especifica uma faixa de variáveis ou funções que podem ser acessadas exclusivamente por membros da classe, de forma que nenhum outro código fora da mesma possa acessá-las;
**'''public''' – Especifica uma faixa de variáveis ou funções que podem ser acessadas por qualquer código no programa, sendo que para as funções internas da classe não é necessário especificar o objeto enquanto que para as outras partes do programa é necessário especificar o objeto a qual estas pertencem.
 
Esta característica de limitar o acesso e manipulação dos membros de uma classe chama-se Encapsulamento. A boa prática no desenho de classes deve sempre forçar o encapsulamento. É raramente necessário ou desejável ter acesso livre e público aos dados internos de uma classe.
 
O encapsulamento visa, primariamente duas metas:
# Eliminar a necessidade de conhecimento da estrutura interna por quem deseja usá-la. Por exemplo, se os objetos precisam manter um conjunto de 4 bytes, isto pode ser conseguido usando-se duas variáveis '''short int''', uma '''int''', um vetor com 4 characteres, ou a variação de qualquer um dos anteriores sem sinal, mas estes detalhes não precisam estar expostos.
# Se a representação interna dos dados for modificada, desde que as tipologias de retorno e de parâmetros das funções públicas mantenham-se inalteradas, não necessitemos de alterar código que utilizem objetos da classe.
 
Ou seja, o encapsulamento simplifica a programação escondendo as partiulariadades da classe e elimina o retrabalho do código por alterações da mesma. Geralmente as funções (métodos) privadas, são auxiliares a outras funções da classe.
 
Se nenhum especificador de acesso for usado, todos os membros e metodos são declarados como privados por padrão.
 
Há dois métodos para definir as funções membro:
* Eles podem ser definidos dentro da classe, o que é apropriado para funções pequenas;
* E funções grandes podem ser definidas fora da classe.
Neste caso terão de ser identificadas como pertencentes à classe e para isso utilizamos o operador de resolução de escopo “'''::'''”.
 
== Construtores e destrutores ==
 
Os constructors são funções membro (métodos) especiais de uma classe. Permitem a inicialização de uma variável membro de um objeto. Ou melhor permitem a construção e a inicialização de objetos das classes. Se não os declararmos o compilador faz isso por nós. e estes construtores têm sempre o mesmo nome que a classe.
 
Os objetos são construídos através destas funções especiais chamados contrutores, até aqui não os declaramos, eram criados automaticamente. Estas tem certas características que as fazem distintas das funções normais, que permitem que as mesmas construam a estrutura lógica inicial do objeto. Desta forma estes métodos são característicos da orientação a objetos e servem para criação dos mesmos.
 
Construtores não podem ser chamados explicitamente como fazemos no caso de funções membro regulares. Eles são apenas executados quando um novo objecto da classe é criado. Portanto, existe apenas um evento capaz de executar um construtor, a instanciação do objeto.
 
As principais característiicas dos construtores são:
 
*Não têm qualquer tipologia de retorno;
*Não podem ser executados por chamada explícita no código;
*São executados logo depois que os tipos básicos do objeto foram criados;
*Inicializam os dados com os valores que o objeto precisa para começar a funcionar corretamente.
 
Além do construtor a linguagem C++, assim como outras linguagens orientadas a objeto, possuem outro tipo de função especialmente criada e gerenciada pela linguagem, os destrutores. Estas são destinadas a desmontar a estrutura do objeto quando o mesmo está sendo encerrado. O destrutor terá o mesmo nome da classe, mas precedido pelo sinal til “~” e também não retorna valor.
 
O destrutor tem as seguintes características:
* O destrutor é chamado quando o objeto está sendo finalizado;
* É usado para libertar qualquer memória que tenha sido alocada;
 
Façamos a classe Dog com o construtor e o destrutor.
 
<source lang=cpp>
class Dog
{
public:
Dog(); //Constructor
~Dog(); //Destructor
void setAge(int age);
int getAge();
void setWeight(int weight);
int getWeight();
void speak();
private:
int age;
int weight;
};
 
Dog::Dog()
{
age = 0;
weight = 0;
cout << "Dog Constructor Called" << endl;
}
 
Dog::~Dog()
{
cout << "Dog Destructor Called" << endl;
}
</source>
 
Repare que o
* Construtor tem o mesmo nome que a classe;
* O destrutor tem o mesmo nome que a classe com o prefixo de tilde” ~”;
* O construtor foi usado para inicializar as variáveis membro, mas noutros exemplos poderia alocar memória, tomar controle de recursos como dispositivos de sistema e executar inicializações de código;
* O destrutor no exemplo não faz nenhuma ação real, para além de fazer o eco informando que foi chamado.
 
== "copy constructors" ==
 
Um "copy constructor" é um construtor especial que toma como argumento a referência de um objeto da mesma classe e cria um novo objeto que é a copia do objeto em referência. Por padrão, o compilador providencia um "copy constructor" que faz a cópia membro por membro do objeto original, construindo um objeto idêntico. Isto é chamado de "shallow copy" ou "member wise"
.
Em algumas situações a cópia de um objeto não é satisfatória, para ver isso vamos ver a classe employer, abaixo:
 
<source lang=cpp>
#include <iostream>
using namespace std;
 
class Employee
{
public:
Employee(char *name, int id);
~Employee();
char *getName(){return _name;}
private://Other Accessor methods
int _id;
char *_name;
};
 
Employee::Employee(char *name, int id)
{
_id = id;
_name = new char[strlen(name) + 1]; //Allocates an character array object
strcpy(_name, name);
}
 
Employee::~Employee()
{
delete[] _name;
}
 
int main()
{
Employee programmer("John",22);
cout << programmer.getName() << endl;
return 0;
}
</source>
 
A função strlen retorna o tamanho da string passada pelo constructor.
Repare que o nome do employee é agora guardado num carácter array dinâmico. é o string lenght +1 para permitir o null terminator usado no estilo c.
 
A função strcpy automaticamente adiciona o null terminator a´string destino.
 
Note também que o destrutor liberta a memoria usada para guardar o employee name, para evitar memory leak.
 
Agora imagine que o john é promovido:
 
<source lang=cpp>
int main()
{
Employee programmer("John",22);
cout << programmer.getName() << endl;
 
//Lots of code ....
 
Employee manager(&programmer);
//Creates a new Employee "manager",
//which is an exact copy of the
//Employee "programmer".
 
return 0;
}
</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".
 
Nos temos 2 pointers ambos contendo o mesmo endereço. Imagine que agora um novo empregado é contratado. quando o nome for atualizado, não apenas iremos alterar o nome do empregado mas também do gerente. Finalmente, quando os objetos deixarem de ser usados e o destrutor da classe fizer a liberação de espaço na memória tentará liberar duas vezes para o mesmo endereço, provocando um erro no sistema de alocação dinâmica de memória, o que forçará o sistema operacional a eliminar o programa da memória.
 
== Ver também ==
* [[Programação orientada a objetos/Classes e Objetos]] - conceitos teóricos
 
{{indentar/fim}}
 
[[Categoria:Programar em C++|Classes]]
 
[[es:Programación en C++/Objetos y Clases]]
[[fr:Programmation C++/Les classes]]
1 653

edições