Capitulo 09 - Classes: Um Exame Mais Profundo Parte 1
Neste Capitulo veremos a utilização de um empacotador pré-processador para evitar em múltiplos erros de definição causados pela inclusão de mais de uma cópia de um arquivo de cabeçalho em um arquivo de código-fonte, no programa Time.h abaixo:
//figura 9.1: Time.h
#ifndef TIME_H
#define TIME_H
//Definição do tipo de dados abstrato Time
class Time
{
public:
Time(); //construtor
void setTime(int, int, int); //inicializa hora, minuto, segundo
void printUniversal(); //imprime no formato de hora militar
void printStandard(); //imprime no formato de hora padrão
private:
int hora; //0-23
int minuto; //0-59
int segundo; //0-59
};
#endif
No Próximo programa Time.cpp definimos o escopo de classe no qual acessamos os membros de classe via nome de um objeto, uma referencia a um objeto ou um ponteiro para um objeto.
//Figura 9.2: Time.cpp
#include <iostream>
#include <iomanip>
#include "Time.h" //inclui a definição da classe Time a parti de Time.h
using std::cout;
using std::setfill;
using std::setw;
/*
O construtor de Time inicializa cada membro de dados como zero.
Assegura que todos os objetos Time iniciem em um estado consistente.
*/
Time::Time()
{
hora = minuto = segundo = 0;
}
/*
configura novo valor de Time utilizando a hora universal; assegura que
os dados permaneçam consistentes configurando valores invalidos como zerovoid
*/
void Time::setTime(int h, int m, int s)
{
hora = (h >= 0 && h < 24) ? h : 0; //valida horas
minuto = (m >= 0 && m < 60) ? m : 0; //valida minutos
segundo = (s >= 0 && s < 60) ? s : 0; //valida segundos
}
//imprime a hora no formato de data/hora universal (HH:MM:SS)
void Time::printUniversal()
{
cout << setfill('0') << setw(2) << hora << ":"
<< setw(2) << minuto << ":" << setw(2) << segundo;
}
//imprime a hora no formato-padrão de data/hora (HH:MM:SS AM ou PM)
void Time::printStandard()
{
cout << ((hora == 0 || hora == 12) ? 12 : hora % 12) << ":"
<< setfill('0') << setw(2) << minuto << ":" << setw(2)
<< segundo << (hora < 12 ? " AM" : " PM");
}
No TimeMain programa para testar a classe Time
//figura 9.3: TimeMain.cpp
#include <iostream>
#include "Time.h"
#include "Time.cpp"
using std::cout;
using std::endl;
int main()
{
Time t; //instancia o objeto t da classe Time
//gera saida de valores iniciais do objeto Time t
cout << "A hora inicial universal = ";
t.printUniversal(); //00:00:00
cout << "\nA hora padrao inicial = ";
t.printStandard(); //12:00:00 AM
t.setTime(13, 27, 6);
//gera saida de novos valores do objeto Time t
cout << "\n\nHora Universal depois de setTime = ";
t.printUniversal(); //13:27:06
cout << "\nHora padrao deppois de setTime = ";
t.printStandard(); //1:27:06
t.setTime(99, 99, 99); //tenta inicialização invalida
//gera saida de valores de t depois de especiicar valores inválidos
cout << "\n\nApos tentar inicialização invalida:\n" << "Hora Universal: ";
t.printUniversal(); //00:00:00
cout << "\nHora padrao: ";
t.printStandard(); //12:00:00 AM
cout << endl;
return 0;
}
ao executar pela IDE codeblocks:
ao executar via terminal linux:
//figura 9.4: OperadoresAcesso.cpp
#include <iostream>
using std::cout;
using std::endl;
//definição da classe Count
class Count
{
public: //dados public são perigosos
//configura o valor do mmbro de dados private x
void setX(int value)
{
x = value;
} //fim da função setX
//imprime o valor do membro de dados private x
void print()
{
cout << x << endl;
}
private:
int x;
};
int main()
{
Count counter; //cria objeto contador
Count *counterPtr = &counter; //cria ponteiro para contador
Count &counterRef = counter; //cria referencia para contador
cout << "Atribui 7 a x a e imprime usando o nome do objeto: ";
counter.setX(1); //configura membro de dados x como 1
counter.print(); //chama a função-membro print
cout << "Atribui 8 para x e imprime usando uma referencia: ";
counterRef.setX(2); //configura membro de dados x como 2
counterRef.print(); //chama a função-membro print
cout << "Atribui 10 para x e imprime usando um ponteiro: ";
counterPtr->setX(3); //configura membro de dados x como 3
counterPtr->print(); //chama a função-membro print
return 0;
}
ao executar na tela no codeblocks:
ao executar na tela via terminal linux:
As funções de acesso podem ler ou exibir dados. Outra utilização das funções de acesso é testar a verdade ou falsidade de condições. O programa das figuras 9.5-9.7 demonstram a noção de uma função utilitária chamada de função auxiliar. Uma função utilitária não faz parte da interface public de uma classe; em vez disso é uma função-membro private que suporta a oprração das funções public da classe.
//figura 9.5: VendasPessoa.h
#ifndef VENDASP_H
#define VENDASP_H
class VendasPessoa
{
public:
VendasPessoa(); //construtor
void getVendasDeUsuario(); //insere as vendas a partir do teclado
void setVendas(int, double); //configura vendas de um mes especifico
void printVendasAnual(); //resume e imprime as vendas
private:
double totalVendasAnual(); //prototipo para fnção utilitaria
double vendas[12]; // 12 estimativas de vendas mensais
}; //fim da classe VendasPessoa
#endif
//Figura 9.6: VendasPessoa.cpp
#include <iostream>
#include <iomanip>
using std::cout;
using std::cin;
using std::endl;
using std::fixed;
using std::setprecision;
//inicializa elementos do array Vendas como 0.0
VendasPessoa::VendasPessoa()
{
for(int i = 0; i < 12; i++)
{
vendas[1] = 0.0;
}
}
//obtém 12 estimativas de vendas do usuario no teclado
void VendasPessoa::getVendasDeUsuario()
{
double vendasFigura;
for(int i = 1; i <= 12; i++)
{
cout << "Digite o valor de vendas do mes: " << i << ": ";
cin >> vendasFigura;
setVendas(i, vendasFigura);
}
}
/*
configura uma das 12 estimativas de vendas mensais; a função subtrai
um valor mensal para o subscrito adequado no array vendas
*/
void VendasPessoa::setVendas(int mes, double valor)
{
//testa a validade do mes e do valor
if(mes >= 1 && mes <= 12 && valor > 0)
vendas[mes - 1] = valor; //ajuda para subscrito 0-11
else //mes ou valor invalido
cout << "Mes de vendas invalidas figura" << endl;
}
//imprime o total das vendas anuais(com a ajuda da função utilitaria)
void VendasPessoa::printVendasAnual()
{
cout << setprecision(2) << fixed
<< "\nO total anual vendas foi: R$"
<< totalVendasAnual() << endl; //chama a função utilitaria
}
//função utlitaria private para somar vendas anuais
double VendasPessoa::totalVendasAnual()
{
double total = 0.0; //inicializa o total
for(int i = 0; i < 12; i++)
total += vendas[i]; //adiciona vendas do mes i ao total
return total;
}
//Figura 9.7:VendasPessoaMain.cpp
//inclui a dfinição da classe VendasPessoa a partir de VendasPessoa.h
#include "VendasPessoa.h"
#include "VendasPessoa.cpp"
int main()
{
VendasPessoa v; //cria o objeto VendasPessoa
v.getVendasDeUsuario(); //anota código sequencial simples;
v.printVendasAnual(); //nenhuma instrução de controle main
return 0;
}
ao executar o programa pelo codeblocks:
ao executar o programa via terminal linux:
Definiremos agora os construtores com argumento-padrão aprimorando a classe Time para demonstrar como os argumentos são implicitamente passados para um construtor.
//Figura 9.8: Time2.h
#ifndef TIME2_H
#define TIME2_H
//Definição do tipo de dados abstrato Time
class Time2
{
public:
Time2(int = 0, int = 0, int = 0); //construtor
void setTime2(int, int, int); //inicializa hora, minuto, segundo
void setHora(int); //configura hora(depois da validação)
void setMinuto(int); //configura minuto(depois da validação)
void setSegundo(int); //configura segundo(depois da validação)
//funções get
int getHora(); //retorna a hora
int getMinuto(); //retorna minuto
int getSegundo(); //retorna o seundo
void printUniversal(); //gera saida da hora no formato universal de data/hora
void printStandard(); //imprime no formato de hora padrão
private:
int hora; //0-23(formato de relogio de 24 horas)
int minuto; //0-59
int segundo; //0-59
};
#endif
O contrutor definido na figura 9.2 inicializou hora, minuto e segundo como 0, isto é meia-noite no horário universal. como outras funções os construtores podem especificar argumentos padrão, e declara o construtor de Time2 para incluir argumentos-padrão, especificando um valor-padrão de zero para cada argumento passado para o construtor.
//figura 9.9: Time2.cpp
#include <iostream>
#include <iomanip>
using std::cout;
using std::setfill;
using std::setw;
/*
O construtor de Time inicializa cada membro de dados como zero.
Assegura que todos os objetos Time iniciem em um estado consistente.
*/
Time2::Time2(int hr, int min, int seg)
{
setTime2(hr, min, seg); //valida e configura Time2
}
/*
configura novo valor de Time utilizando a hora universal; assegura que
os dados permaneçam consistentes configurandfo valores invalidos como zero
*/
void Time2::setTime2(int h, int m, int s)
{
setHora(h); //configura campo private hora
setMinuto(m); //configura campo private minuto
setSegundo(s); //configura campo private segundo
}
//configura valor de hora
void Time2::setHora(int h)
{
hora = (h >= 0 && h < 24) ? h : 0; //valida horas
}
//configura valor de minuto
void Time2::setMinuto(int m)
{
minuto = (m >= 0 && m < 60) ? m : 0; //valida minutos
}
//configura o valor de segundo
void Time2::setSegundo(int s)
{
segundo = (s >= 0 && s < 60) ? s : 0; //valida segundos
}
//retorna valor de hora
int Time2::getHora()
{
return hora;
}
//retorna valor de minuto
int Time2::getMinuto()
{
return minuto;
}
//retorna o valor de segundo
int Time2::getSegundo()
{
return segundo;
}
//imprime a hora no formato de data/hora universal (HH:MM:SS)
void Time2::printUniversal()
{
cout << setfill('0') << setw(2) << getHora() << ":"
<< setw(2) << getMinuto() << ":" << setw(2) << getSegundo();
}
//imprime a hora no formato-padrão de data/hora (HH:MM:SS AM ou PM)
void Time2::printStandard()
{
cout << ((getHora() == 0 || getHora() == 12) ? 12 : getHora() % 12)
<< ":" << setfill('0') << setw(2) << getMinuto()
<< ":" << setw(2) << getSegundo() << (hora < 12 ? " AM" : " PM");
}
//Figura 9.10: Time2Main.cpp
#include <iostream>
using std::cout;
using std::endl;
#include "Time2.h"
#include "Time2.cpp"
//Porgrama pata testar a classe Time simples
int main()
{
Time2 t1; //todos os rgumentos convertidos para sua configuracao-padrao
Time2 t2(2); //hora especificada; minuto e segundo convertidos para o padrao
Time2 t3(21, 34); //hora e minuto especificados; segundo convertido para o padrao
Time2 t4(12, 25, 42); //hora, minuto e segundo especificado
Time2 t5(27, 74, 99); //valores invalidos especificados
cout << "Construido com:\n\nt1: todos os argumentos padrao\n ";
t1.printUniversal(); //00:00:00
cout << "\n ";
t1.printStandard(); //12:00:00 AM
cout << "\n\nt2: hora especificada; minuto e segundo padrao\n ";
t2.printUniversal(); //02:00:00
cout << "\n ";
t2.printStandard(); //2:00:00 AM
cout << "\n\nt3: hora, e minuto especificado; segundo padrao\n ";
t3.printUniversal(); //21:34:00
cout << "\n ";
t3.printStandard(); //9:34:00 PM
cout << "\n\nt4: hora, minuto e segundo especificado\n ";
t4.printUniversal(); //12:25:42
cout << "\n ";
t4.printStandard(); //12:25:42 PM
cout << "\n\nt5: Todos os valores invalidos especiicados\n ";
t5.printUniversal(); //00:00:00
cout << "\n ";
t5.printStandard(); //12:00:00 AM
cout << endl;
return 0;
}
ao executar no codeblocks:
ao executar no terminal linux:
definir construtores como argumento-padrão, veremos como os destrutores são utilizados para realizar uma 'faxina de terminação' em um objeto antes dele ser destruido e quando os construtores e destrutores são chamados e a ordem em que são chamados.
//Figura 9.11: ConstrutorDestrutor.h
#include <string>
#ifndef CREATE_H
#define CREATE_H
using std::string;
class ConstrutorDestrutor
{
public:
ConstrutorDestrutor(int, string); //construtor
~ConstrutorDestrutor(); //destrutor
private:
int objetoID; //Numero de ID do objeto
string mensagem; //mensagem descrevendo o objeto
};
#endif
//Figura 9.12: ConstrutorDestrutor.cpp
#include <string>
#include <iostream>
#include "ConstrutorDestrutor.h"
using std::cout;
using std::endl;
//construtor
ConstrutorDestrutor::ConstrutorDestrutor(int ID, string mensagemString)
{
objetoID = ID; //configura o numero de ID do objeto
mensagem = mensagemString; //confiura mensagem descritiva do objeto
cout << "Objeto " << objetoID << " correr construtor "
<< mensagem << endl;
}
//destructor
ConstrutorDestrutor::~ConstrutorDestrutor()
{
//gera saida de nova linha para certos objetos; ajuda a legabilidade
cout << (objetoID == 1 || objetoID == 6 ? "\n" : "");
cout << "Objeto " << objetoID << " correr destruidor "
<< mensagem << endl;
}
//Figura 9.13: ConstrutorDestrutorMain.cpp
#include <iostream>
#include "ConstrutorDestrutor.h"
#include "ConstrutorDestrutor.cpp"
using std::cout;
using std::endl;
void criar(void); //prototipo
ConstrutorDestrutor primeiro(1, "(Global antes do main)" ); //objeto global
int main()
{
cout << "\nFUNCAO MAIN: COMECO DE EXECUCAO" << endl;
ConstrutorDestrutor segundo(2, "(Local automatic em main)" );
static ConstrutorDestrutor terceiro(3, "(Local static em main)" );
criar(); //chama funcao para criar objetos
cout << "\nCRIANDO FUNCAO: INICIO EXECUCAO" << endl;
ConstrutorDestrutor quarto(4, "(Local automatico main)" );
cout << "\nFUNCAO MAIN: FINALIZA EXECUCAO" << endl;
return 0;
}
//funcao para criar objetos
void criar(void)
{
cout << "\nCRIANDO FUNCAO: INICIO EXECUCAO" << endl;
ConstrutorDestrutor quinto(5, "(Criando local automaticamente)");
static ConstrutorDestrutor sexto(6, "(Criando local estatico)");
ConstrutorDestrutor setimo(7, "(Criacao local automatica)");
cout << "\nCRIANDO FUNCAO: FINALIZA EXECUCAO" << endl;
}
ao executar via codeblocks:
ao executar vi terminal linux:
Estudo de caso de uma classe Time: uma armadilha sutil:
os erros de lógica que podem ocorrer quando uma funcao-membro public de uma classe retorna uma referencia a dados private.
/*
Estudo de caso de uma classe Time: uma armadilha sutil -
retornar uma referencia a um membro de dados private
Figura 9.14: Time3.h
Declaracao da classe Time3.
Funcoes-membro definidas em Time.cpp
*/
//impede multiplas inclusoes de arquivo de cabecalho
#ifndef TIME3_H
#define TIME3_H
class Time3
{
public:
Time3(int = 0, int = 0, int = 0);
void setTime3(int, int, int);
int getHora();
int &badSetHora(int); //retorno de referencia PERIGOSO
private:
int hora;
int minuto;
int segundo;
};
#endif
/*
Estudo de caso de uma classe Time: uma armadilha sutil -
retornar uma referencia a um membro de dados private
Figura 9.15: Time3.cpp
Definicoes de funcao-membro para a classe Time3.
*/
/*
funcao constructor para inicializar dados private;
chama a funcao-membro setTime3 para configurar variaveis;
valores-padrao sao 0 (ver definicao de classe)
*/
Time3::Time3(int hr, int min, int seg)
{
setTime3(hr, min, seg);
}
//configura valores de hora, minuto e segundo
void Time3::setTime3(int h, int m, int s)
{
hora = (h >= 0 && h < 24) ? h : 0; //valida horas
minuto = (m >= 0 && m < 60) ? m : 0; //valida minutos
segundo = (s >= 0 && s < 60) ? s : 0; //valida segundos
}
//retorna valor de hora
int Time3::getHora()
{
return hora;
}
/*
PRATICA DE PROGRAMACAO RUIM:
Retorna uma referencia a um membro de dados private.
*/
int &Time3::badSetHora(int hh)
{
hora = (hh >= 0 && hh < 24) ? hh : 0;
return hora; //retorno de referencia PERIGOSO
}
/*
Estudo de caso de uma classe Time: uma armadilha sutil -
retornar uma referencia a um membro de dados private
Demonstrando uma funcao-membro public que
retorna uma referencia a um mebro de dados private.
*/
#include <iostream>
#include "Time3.h"
#include "Time3.cpp"
using std::cout;
using std::endl;
int main()
{
Time3 t; //cria o objeto Time3
//incializa horaRef com a referencia retornado por badSetHora
int &horaRef = t.badSetHora(20); //20 e a valida hora
cout << "Valida hora depois de modificado: " <<horaRef;
horaRef = 30; //use horaRef em set valor invalido em Time3 objeto t
cout << "\n Invalido hora antes notificada: " << t.getHora();
/*
chamada de funcao perigosa que retorna
com valor de referencia a ser usado
*/
t.badSetHora(12) = 74; //atribui outro valor invalido em hora
cout << "\n\n********************************************************\n"
<< "PROGRAMACAO PRATICA!!!!!!!!!!!!\n"
<< "t.badSethora(12) valor invalido em hora: "
<< t.getHora()
<< "\n**********************************************************" << endl;
return 0;
}
ao executar no codeblocks:
ao executar via terminal linux:
Atribuir os membros de dados de um objeto aqueles de outro objeto por atribuição-padrão de membro a membro.
//Figura 9.17: Date.h
#ifndef DATE_H
#define DATE_H
//definicao da classe Date
class Date
{
public:
Date(int = 1, int = 1, int = 2000); //construtor-padrao
void print();
private:
int mes;
int dia;
int ano;
};
#endif
//Figura 9.18: Date.cpp
#include <iostream>
using std::cout;
using std::endl;
//construtor Date (deve fazer uma verificao de intervalo)
Date::Date(int d, int m, int y)
{
dia = d;
mes = m;
ano = y;
}
//imprime Date no formato DD/MM/YYYY
void Date::print()
{
cout << mes << '/' << dia << '/' << ano;
}
//Figura 9.19: DateMain.cpp
#include <iostream>
#include "Date.h" //inclui a definicao da classe Date a partir de Date.h
#include "Date.cpp" //inclui a definicao da funcao Date a partir de Date.cpp
using std::cout;
using std::endl;
int main()
{
Date data1(8, 24, 2010);
Date data2;
cout << "data1 = ";
data1.print();
cout << "\ndata2 = ";
data2.print();
data2 = data1; //atribuicao padrao de membro a membro
cout << "\n\nApos a atribuicao de membro padrao, data2 = ";
data2.print();
cout << endl;
return 0;
}
ao executar no codeblocks:
ao executar via terminal linux:
Aqui terminanos mais este capitulo, e até a proxíma
//figura 9.1: Time.h
#ifndef TIME_H
#define TIME_H
//Definição do tipo de dados abstrato Time
class Time
{
public:
Time(); //construtor
void setTime(int, int, int); //inicializa hora, minuto, segundo
void printUniversal(); //imprime no formato de hora militar
void printStandard(); //imprime no formato de hora padrão
private:
int hora; //0-23
int minuto; //0-59
int segundo; //0-59
};
#endif
No Próximo programa Time.cpp definimos o escopo de classe no qual acessamos os membros de classe via nome de um objeto, uma referencia a um objeto ou um ponteiro para um objeto.
//Figura 9.2: Time.cpp
#include <iostream>
#include <iomanip>
#include "Time.h" //inclui a definição da classe Time a parti de Time.h
using std::cout;
using std::setfill;
using std::setw;
/*
O construtor de Time inicializa cada membro de dados como zero.
Assegura que todos os objetos Time iniciem em um estado consistente.
*/
Time::Time()
{
hora = minuto = segundo = 0;
}
/*
configura novo valor de Time utilizando a hora universal; assegura que
os dados permaneçam consistentes configurando valores invalidos como zerovoid
*/
void Time::setTime(int h, int m, int s)
{
hora = (h >= 0 && h < 24) ? h : 0; //valida horas
minuto = (m >= 0 && m < 60) ? m : 0; //valida minutos
segundo = (s >= 0 && s < 60) ? s : 0; //valida segundos
}
//imprime a hora no formato de data/hora universal (HH:MM:SS)
void Time::printUniversal()
{
cout << setfill('0') << setw(2) << hora << ":"
<< setw(2) << minuto << ":" << setw(2) << segundo;
}
//imprime a hora no formato-padrão de data/hora (HH:MM:SS AM ou PM)
void Time::printStandard()
{
cout << ((hora == 0 || hora == 12) ? 12 : hora % 12) << ":"
<< setfill('0') << setw(2) << minuto << ":" << setw(2)
<< segundo << (hora < 12 ? " AM" : " PM");
}
No TimeMain programa para testar a classe Time
//figura 9.3: TimeMain.cpp
#include <iostream>
#include "Time.h"
#include "Time.cpp"
using std::cout;
using std::endl;
int main()
{
Time t; //instancia o objeto t da classe Time
//gera saida de valores iniciais do objeto Time t
cout << "A hora inicial universal = ";
t.printUniversal(); //00:00:00
cout << "\nA hora padrao inicial = ";
t.printStandard(); //12:00:00 AM
t.setTime(13, 27, 6);
//gera saida de novos valores do objeto Time t
cout << "\n\nHora Universal depois de setTime = ";
t.printUniversal(); //13:27:06
cout << "\nHora padrao deppois de setTime = ";
t.printStandard(); //1:27:06
t.setTime(99, 99, 99); //tenta inicialização invalida
//gera saida de valores de t depois de especiicar valores inválidos
cout << "\n\nApos tentar inicialização invalida:\n" << "Hora Universal: ";
t.printUniversal(); //00:00:00
cout << "\nHora padrao: ";
t.printStandard(); //12:00:00 AM
cout << endl;
return 0;
}
ao executar pela IDE codeblocks:
ao executar via terminal linux:
//figura 9.4: OperadoresAcesso.cpp
#include <iostream>
using std::cout;
using std::endl;
//definição da classe Count
class Count
{
public: //dados public são perigosos
//configura o valor do mmbro de dados private x
void setX(int value)
{
x = value;
} //fim da função setX
//imprime o valor do membro de dados private x
void print()
{
cout << x << endl;
}
private:
int x;
};
int main()
{
Count counter; //cria objeto contador
Count *counterPtr = &counter; //cria ponteiro para contador
Count &counterRef = counter; //cria referencia para contador
cout << "Atribui 7 a x a e imprime usando o nome do objeto: ";
counter.setX(1); //configura membro de dados x como 1
counter.print(); //chama a função-membro print
cout << "Atribui 8 para x e imprime usando uma referencia: ";
counterRef.setX(2); //configura membro de dados x como 2
counterRef.print(); //chama a função-membro print
cout << "Atribui 10 para x e imprime usando um ponteiro: ";
counterPtr->setX(3); //configura membro de dados x como 3
counterPtr->print(); //chama a função-membro print
return 0;
}
ao executar na tela no codeblocks:
ao executar na tela via terminal linux:
As funções de acesso podem ler ou exibir dados. Outra utilização das funções de acesso é testar a verdade ou falsidade de condições. O programa das figuras 9.5-9.7 demonstram a noção de uma função utilitária chamada de função auxiliar. Uma função utilitária não faz parte da interface public de uma classe; em vez disso é uma função-membro private que suporta a oprração das funções public da classe.
//figura 9.5: VendasPessoa.h
#ifndef VENDASP_H
#define VENDASP_H
class VendasPessoa
{
public:
VendasPessoa(); //construtor
void getVendasDeUsuario(); //insere as vendas a partir do teclado
void setVendas(int, double); //configura vendas de um mes especifico
void printVendasAnual(); //resume e imprime as vendas
private:
double totalVendasAnual(); //prototipo para fnção utilitaria
double vendas[12]; // 12 estimativas de vendas mensais
}; //fim da classe VendasPessoa
#endif
//Figura 9.6: VendasPessoa.cpp
#include <iostream>
#include <iomanip>
using std::cout;
using std::cin;
using std::endl;
using std::fixed;
using std::setprecision;
//inicializa elementos do array Vendas como 0.0
VendasPessoa::VendasPessoa()
{
for(int i = 0; i < 12; i++)
{
vendas[1] = 0.0;
}
}
//obtém 12 estimativas de vendas do usuario no teclado
void VendasPessoa::getVendasDeUsuario()
{
double vendasFigura;
for(int i = 1; i <= 12; i++)
{
cout << "Digite o valor de vendas do mes: " << i << ": ";
cin >> vendasFigura;
setVendas(i, vendasFigura);
}
}
/*
configura uma das 12 estimativas de vendas mensais; a função subtrai
um valor mensal para o subscrito adequado no array vendas
*/
void VendasPessoa::setVendas(int mes, double valor)
{
//testa a validade do mes e do valor
if(mes >= 1 && mes <= 12 && valor > 0)
vendas[mes - 1] = valor; //ajuda para subscrito 0-11
else //mes ou valor invalido
cout << "Mes de vendas invalidas figura" << endl;
}
//imprime o total das vendas anuais(com a ajuda da função utilitaria)
void VendasPessoa::printVendasAnual()
{
cout << setprecision(2) << fixed
<< "\nO total anual vendas foi: R$"
<< totalVendasAnual() << endl; //chama a função utilitaria
}
//função utlitaria private para somar vendas anuais
double VendasPessoa::totalVendasAnual()
{
double total = 0.0; //inicializa o total
for(int i = 0; i < 12; i++)
total += vendas[i]; //adiciona vendas do mes i ao total
return total;
}
//Figura 9.7:VendasPessoaMain.cpp
//inclui a dfinição da classe VendasPessoa a partir de VendasPessoa.h
#include "VendasPessoa.h"
#include "VendasPessoa.cpp"
int main()
{
VendasPessoa v; //cria o objeto VendasPessoa
v.getVendasDeUsuario(); //anota código sequencial simples;
v.printVendasAnual(); //nenhuma instrução de controle main
return 0;
}
ao executar o programa pelo codeblocks:
ao executar o programa via terminal linux:
Definiremos agora os construtores com argumento-padrão aprimorando a classe Time para demonstrar como os argumentos são implicitamente passados para um construtor.
//Figura 9.8: Time2.h
#ifndef TIME2_H
#define TIME2_H
//Definição do tipo de dados abstrato Time
class Time2
{
public:
Time2(int = 0, int = 0, int = 0); //construtor
void setTime2(int, int, int); //inicializa hora, minuto, segundo
void setHora(int); //configura hora(depois da validação)
void setMinuto(int); //configura minuto(depois da validação)
void setSegundo(int); //configura segundo(depois da validação)
//funções get
int getHora(); //retorna a hora
int getMinuto(); //retorna minuto
int getSegundo(); //retorna o seundo
void printUniversal(); //gera saida da hora no formato universal de data/hora
void printStandard(); //imprime no formato de hora padrão
private:
int hora; //0-23(formato de relogio de 24 horas)
int minuto; //0-59
int segundo; //0-59
};
#endif
O contrutor definido na figura 9.2 inicializou hora, minuto e segundo como 0, isto é meia-noite no horário universal. como outras funções os construtores podem especificar argumentos padrão, e declara o construtor de Time2 para incluir argumentos-padrão, especificando um valor-padrão de zero para cada argumento passado para o construtor.
//figura 9.9: Time2.cpp
#include <iostream>
#include <iomanip>
using std::cout;
using std::setfill;
using std::setw;
/*
O construtor de Time inicializa cada membro de dados como zero.
Assegura que todos os objetos Time iniciem em um estado consistente.
*/
Time2::Time2(int hr, int min, int seg)
{
setTime2(hr, min, seg); //valida e configura Time2
}
/*
configura novo valor de Time utilizando a hora universal; assegura que
os dados permaneçam consistentes configurandfo valores invalidos como zero
*/
void Time2::setTime2(int h, int m, int s)
{
setHora(h); //configura campo private hora
setMinuto(m); //configura campo private minuto
setSegundo(s); //configura campo private segundo
}
//configura valor de hora
void Time2::setHora(int h)
{
hora = (h >= 0 && h < 24) ? h : 0; //valida horas
}
//configura valor de minuto
void Time2::setMinuto(int m)
{
minuto = (m >= 0 && m < 60) ? m : 0; //valida minutos
}
//configura o valor de segundo
void Time2::setSegundo(int s)
{
segundo = (s >= 0 && s < 60) ? s : 0; //valida segundos
}
//retorna valor de hora
int Time2::getHora()
{
return hora;
}
//retorna valor de minuto
int Time2::getMinuto()
{
return minuto;
}
//retorna o valor de segundo
int Time2::getSegundo()
{
return segundo;
}
//imprime a hora no formato de data/hora universal (HH:MM:SS)
void Time2::printUniversal()
{
cout << setfill('0') << setw(2) << getHora() << ":"
<< setw(2) << getMinuto() << ":" << setw(2) << getSegundo();
}
//imprime a hora no formato-padrão de data/hora (HH:MM:SS AM ou PM)
void Time2::printStandard()
{
cout << ((getHora() == 0 || getHora() == 12) ? 12 : getHora() % 12)
<< ":" << setfill('0') << setw(2) << getMinuto()
<< ":" << setw(2) << getSegundo() << (hora < 12 ? " AM" : " PM");
}
//Figura 9.10: Time2Main.cpp
#include <iostream>
using std::cout;
using std::endl;
#include "Time2.h"
#include "Time2.cpp"
//Porgrama pata testar a classe Time simples
int main()
{
Time2 t1; //todos os rgumentos convertidos para sua configuracao-padrao
Time2 t2(2); //hora especificada; minuto e segundo convertidos para o padrao
Time2 t3(21, 34); //hora e minuto especificados; segundo convertido para o padrao
Time2 t4(12, 25, 42); //hora, minuto e segundo especificado
Time2 t5(27, 74, 99); //valores invalidos especificados
cout << "Construido com:\n\nt1: todos os argumentos padrao\n ";
t1.printUniversal(); //00:00:00
cout << "\n ";
t1.printStandard(); //12:00:00 AM
cout << "\n\nt2: hora especificada; minuto e segundo padrao\n ";
t2.printUniversal(); //02:00:00
cout << "\n ";
t2.printStandard(); //2:00:00 AM
cout << "\n\nt3: hora, e minuto especificado; segundo padrao\n ";
t3.printUniversal(); //21:34:00
cout << "\n ";
t3.printStandard(); //9:34:00 PM
cout << "\n\nt4: hora, minuto e segundo especificado\n ";
t4.printUniversal(); //12:25:42
cout << "\n ";
t4.printStandard(); //12:25:42 PM
cout << "\n\nt5: Todos os valores invalidos especiicados\n ";
t5.printUniversal(); //00:00:00
cout << "\n ";
t5.printStandard(); //12:00:00 AM
cout << endl;
return 0;
}
ao executar no codeblocks:
ao executar no terminal linux:
definir construtores como argumento-padrão, veremos como os destrutores são utilizados para realizar uma 'faxina de terminação' em um objeto antes dele ser destruido e quando os construtores e destrutores são chamados e a ordem em que são chamados.
//Figura 9.11: ConstrutorDestrutor.h
#include <string>
#ifndef CREATE_H
#define CREATE_H
using std::string;
class ConstrutorDestrutor
{
public:
ConstrutorDestrutor(int, string); //construtor
~ConstrutorDestrutor(); //destrutor
private:
int objetoID; //Numero de ID do objeto
string mensagem; //mensagem descrevendo o objeto
};
#endif
//Figura 9.12: ConstrutorDestrutor.cpp
#include <string>
#include <iostream>
#include "ConstrutorDestrutor.h"
using std::cout;
using std::endl;
//construtor
ConstrutorDestrutor::ConstrutorDestrutor(int ID, string mensagemString)
{
objetoID = ID; //configura o numero de ID do objeto
mensagem = mensagemString; //confiura mensagem descritiva do objeto
cout << "Objeto " << objetoID << " correr construtor "
<< mensagem << endl;
}
//destructor
ConstrutorDestrutor::~ConstrutorDestrutor()
{
//gera saida de nova linha para certos objetos; ajuda a legabilidade
cout << (objetoID == 1 || objetoID == 6 ? "\n" : "");
cout << "Objeto " << objetoID << " correr destruidor "
<< mensagem << endl;
}
//Figura 9.13: ConstrutorDestrutorMain.cpp
#include <iostream>
#include "ConstrutorDestrutor.h"
#include "ConstrutorDestrutor.cpp"
using std::cout;
using std::endl;
void criar(void); //prototipo
ConstrutorDestrutor primeiro(1, "(Global antes do main)" ); //objeto global
int main()
{
cout << "\nFUNCAO MAIN: COMECO DE EXECUCAO" << endl;
ConstrutorDestrutor segundo(2, "(Local automatic em main)" );
static ConstrutorDestrutor terceiro(3, "(Local static em main)" );
criar(); //chama funcao para criar objetos
cout << "\nCRIANDO FUNCAO: INICIO EXECUCAO" << endl;
ConstrutorDestrutor quarto(4, "(Local automatico main)" );
cout << "\nFUNCAO MAIN: FINALIZA EXECUCAO" << endl;
return 0;
}
//funcao para criar objetos
void criar(void)
{
cout << "\nCRIANDO FUNCAO: INICIO EXECUCAO" << endl;
ConstrutorDestrutor quinto(5, "(Criando local automaticamente)");
static ConstrutorDestrutor sexto(6, "(Criando local estatico)");
ConstrutorDestrutor setimo(7, "(Criacao local automatica)");
cout << "\nCRIANDO FUNCAO: FINALIZA EXECUCAO" << endl;
}
ao executar via codeblocks:
ao executar vi terminal linux:
Estudo de caso de uma classe Time: uma armadilha sutil:
os erros de lógica que podem ocorrer quando uma funcao-membro public de uma classe retorna uma referencia a dados private.
/*
Estudo de caso de uma classe Time: uma armadilha sutil -
retornar uma referencia a um membro de dados private
Figura 9.14: Time3.h
Declaracao da classe Time3.
Funcoes-membro definidas em Time.cpp
*/
//impede multiplas inclusoes de arquivo de cabecalho
#ifndef TIME3_H
#define TIME3_H
class Time3
{
public:
Time3(int = 0, int = 0, int = 0);
void setTime3(int, int, int);
int getHora();
int &badSetHora(int); //retorno de referencia PERIGOSO
private:
int hora;
int minuto;
int segundo;
};
#endif
/*
Estudo de caso de uma classe Time: uma armadilha sutil -
retornar uma referencia a um membro de dados private
Figura 9.15: Time3.cpp
Definicoes de funcao-membro para a classe Time3.
*/
/*
funcao constructor para inicializar dados private;
chama a funcao-membro setTime3 para configurar variaveis;
valores-padrao sao 0 (ver definicao de classe)
*/
Time3::Time3(int hr, int min, int seg)
{
setTime3(hr, min, seg);
}
//configura valores de hora, minuto e segundo
void Time3::setTime3(int h, int m, int s)
{
hora = (h >= 0 && h < 24) ? h : 0; //valida horas
minuto = (m >= 0 && m < 60) ? m : 0; //valida minutos
segundo = (s >= 0 && s < 60) ? s : 0; //valida segundos
}
//retorna valor de hora
int Time3::getHora()
{
return hora;
}
/*
PRATICA DE PROGRAMACAO RUIM:
Retorna uma referencia a um membro de dados private.
*/
int &Time3::badSetHora(int hh)
{
hora = (hh >= 0 && hh < 24) ? hh : 0;
return hora; //retorno de referencia PERIGOSO
}
/*
Estudo de caso de uma classe Time: uma armadilha sutil -
retornar uma referencia a um membro de dados private
Demonstrando uma funcao-membro public que
retorna uma referencia a um mebro de dados private.
*/
#include <iostream>
#include "Time3.h"
#include "Time3.cpp"
using std::cout;
using std::endl;
int main()
{
Time3 t; //cria o objeto Time3
//incializa horaRef com a referencia retornado por badSetHora
int &horaRef = t.badSetHora(20); //20 e a valida hora
cout << "Valida hora depois de modificado: " <<horaRef;
horaRef = 30; //use horaRef em set valor invalido em Time3 objeto t
cout << "\n Invalido hora antes notificada: " << t.getHora();
/*
chamada de funcao perigosa que retorna
com valor de referencia a ser usado
*/
t.badSetHora(12) = 74; //atribui outro valor invalido em hora
cout << "\n\n********************************************************\n"
<< "PROGRAMACAO PRATICA!!!!!!!!!!!!\n"
<< "t.badSethora(12) valor invalido em hora: "
<< t.getHora()
<< "\n**********************************************************" << endl;
return 0;
}
ao executar no codeblocks:
ao executar via terminal linux:
Atribuir os membros de dados de um objeto aqueles de outro objeto por atribuição-padrão de membro a membro.
//Figura 9.17: Date.h
#ifndef DATE_H
#define DATE_H
//definicao da classe Date
class Date
{
public:
Date(int = 1, int = 1, int = 2000); //construtor-padrao
void print();
private:
int mes;
int dia;
int ano;
};
#endif
//Figura 9.18: Date.cpp
#include <iostream>
using std::cout;
using std::endl;
//construtor Date (deve fazer uma verificao de intervalo)
Date::Date(int d, int m, int y)
{
dia = d;
mes = m;
ano = y;
}
//imprime Date no formato DD/MM/YYYY
void Date::print()
{
cout << mes << '/' << dia << '/' << ano;
}
//Figura 9.19: DateMain.cpp
#include <iostream>
#include "Date.h" //inclui a definicao da classe Date a partir de Date.h
#include "Date.cpp" //inclui a definicao da funcao Date a partir de Date.cpp
using std::cout;
using std::endl;
int main()
{
Date data1(8, 24, 2010);
Date data2;
cout << "data1 = ";
data1.print();
cout << "\ndata2 = ";
data2.print();
data2 = data1; //atribuicao padrao de membro a membro
cout << "\n\nApos a atribuicao de membro padrao, data2 = ";
data2.print();
cout << endl;
return 0;
}
ao executar no codeblocks:
ao executar via terminal linux:
Aqui terminanos mais este capitulo, e até a proxíma
Comentários
Postar um comentário