Física Computacional 1. Funções: a. Inicialização de argumentos. b. Overloading. 2. Revisão de classes 3. Classes parte 2 a. Overloading de operadores. 4. Gestão de projectos com Dev-C++ 5. Gestão de projectos com GNU Make, Makefiles Pedro.Martins@cern.ch 19-10-2009 Física Computacional - MEFT 2009/10 P. Bicudo & P. Martins 1
Em C++ é possível definir valores iniciais de argumentos dentro da declaração de uma função. Esta regra aplica-se também a métodos em classes. float Power(float x, int p=2){ if(p==0) return 1; else if(p==1) return x; for(int i=1;i<p;i++) x*=x; return x; int main(){ int x = 3; cout << x^2: " << Power(x) <<endl; cout << x^3: " << Power(x,3) <<endl; return 0; Funções - inicialização de argumentos 19-10-2009 Física Computacional - MEFT 2009/10 P. Bicudo & P. Martins 2
Contrariamente ao C, o C++ permite fazer a declaração múltipla de funções com o mesmo nome. A isto chama-se function overloading. Esta regra aplica-se também a métodos em classes (ex: constructores, ver aula anterior). Contudo, existem algumas regras: O overload não pode ser feito ao nível do retorno da função. Pelo menos o tipo de um argumento deverá ser diferente. Não pode haver ambiguidade com o número os argumentos: float Myfunc(float x, float y){return x*y; //permitido (float, float) int Myfunc(int x, int y){return x*y;// permitido (int,int) int Myfunc(int x){return x*3; //permitido (int) bool Myfunc(int x,int y=1){return x*y;//ambiguo com (int) e (int,int)!! Overloading de funções 19-10-2009 Física Computacional - MEFT 2009/10 P. Bicudo & P. Martins 3
Uma classe é constituída por membros e métodos. À instância de uma classe chamamos objecto. O operador de scope :: permite definir métodos fora da declaração da classe. Constructors e destructors são funções especiais numa classe: Chamadas automaticamente quando declaramos um objecto. Possibilidade de overloading de constructores e destructores default. Três tipos de construtores automáticos: default, cópia e atribuição. Assim que um constructor é definido, o compilador não cria o construtor automático: MyClass::MyClass(){; //declaracao de constructor default Três tipos de acesso: private, protected e public. As classes também possuem variáveis e métodos static e const. Classes - revisão 19-10-2009 Física Computacional - MEFT 2009/10 P. Bicudo & P. Martins 4
Já vimos operadores a serem utilizados em tipos normais de C++. Este operadores, tal como o nome indica, definem operações em tipos conhecidos. float a = 2.3, b=3.2; float c = a+b; //operacao conhecida 5.5 = 2.3 + 3.2 Uma classe, uma vez que se comporta como um tipo, também pode ter operadores definidos ou redefinidos (overloaded). No entanto, é necessário explicar ao compilador como queremos que essas operações se façam. Também é possível redefinir operadores que poderiam ser criados automaticamente pelo compilador, como o operador de cópia. Lista de operadores que podem ser redefinidos: + - * / = < > += -= *= /= << >> <<= >>= ==!= <= >= ++ -- % & ^! ~ &= ^= = && %= [] (), - >* -> new delete new[] delete[] Classes operator overloading 19-10-2009 Física Computacional - MEFT 2009/10 P. Bicudo & P. Martins 5
Para (re)definir operadores usa-se a sintaxe para funções de operador: tipo operator simbolo (parametros) { (instrucoes); Consideremos o caso em que o operador + (soma) é redefinido na classe Matrix (ver exemplo seguinte). As seguintes instruções são equivalentes: a = b + c; //Matrix a,b,c a = b.operator+(c); //Matrix a,b,c Em alguns casos, a forma como os operadores se relacionam com os parâmetros pode não ser trivial: Expressão operator Método na classe Operador global @a + - * &! ~ ++ -- A::operator@() operator@(a) a@ ++ -- A::operator@(int) operator@(a,int) a@b + - * / % ^ & < > ==!= <= >= << >> &&, A::operator@ (B) operator@(a,b) a@b = += -= *= /= %= ^= &= = <<= >>= [] A::operator@ (B) - a(b, c...) () A::operator() (B, C...) - a->x -> A::operator->() - Classes operator overloading (cont.) 19-10-2009 Física Computacional - MEFT 2009/10 P. Bicudo & P. Martins 6
class Matrix{ private: int fnrows, fncols; void AllocateMatrix(); public: vector< vector <float> > fm; Matrix(){; Matrix(int nrows, int ncols); matrix.cpp Matrix Matrix::operator+ (Matrix b){ Matrix tmp(b.fnrows,b.fncols); for(int i=0;i< (signed int)fm.size();i++) for(int j=0;j< fm[i].size(); j++) tmp.fm[i][j] = fm[i][j] + b.fm[i][j]; return tmp; ; void SetNRows(int nrows){fnrows = nrows; int GetNRows() const {return fnrows; void SetNCols(int ncols){fncols = ncols; int GetNCols() const {return fncols; void Print() const; //operators Matrix operator+ (Matrix b); matrix.h int main(){ int nrows = 3, ncols = 3; Matrix m(nrows,ncols),n(nrows,ncols); for(int i=0;i<nrows;i++){ for(int j=0;j<ncols;j++){ m.fm[i][j] = i; n.fm[i][j] = j; m.print(); n.print(); const Matrix z = m+n; z.print(); return 0; main.cpp Operator overloading - exemplo 19-10-2009 Física Computacional - MEFT 2009/10 P. Bicudo & P. Martins 7
Programar usando modularidade garante que o código é reaproveitado nós e outras pessoas. Da mesma forma que um namespace agrupa funções e variáveis semelhantes, é conveniente guardar este tipo de containers em ficheiros de trabalho diferentes. Com ficheiros diferentes, é possível separar tarefas e ter várias pessoas a trabalhar no mesmo projecto, sem nos preocuparmos com alterações simultâneas. O Dev-C++ disponibiliza esta possibilidade. Basta começar/abrir um novo projecto. Terão inicialmente o file main.cpp com a função main. Para adicionar mais ficheiros, basta clicar com o botão direito no projecto ou abrir um ficheiro novo. Uma regra a não esquecer é que todos os nossos header files deverão ser incluidos nos correspondentes *.cpp. O compilador não compila header files! Gestão de projectos Dev-C++ 19-10-2009 Física Computacional - MEFT 2009/10 P. Bicudo & P. Martins 8
O programa GNU Make permite a utilização de makefiles. Um makefile não é parte integrante do GNU C/C++, podendo ser usando com outros programas. Antes de escrevermos um makefile, temos de perceber como funciona o linker. O linker cria object files (não confundir com objectos de programação!), código pré-compilado que pode ser incluido com outros do mesmo género: Cria automaticamente matrix.o e main.o g++ -Wall c matrix.cpp main.cpp Agora juntamos os 2 files no executavel matrix g++ -o matrix matrix.o main.o Gestão de projectos - Makefiles 19-10-2009 Física Computacional - MEFT 2009/10 P. Bicudo & P. Martins 9
matrix.o: matrix.cpp matrix.h g++ -c Wall matrix.cpp main.o: main.cpp g++ -c Wall main.cpp matrix: main.o matrix.o g++ -o matrix main.o matrix.o Desta forma, quando fazemos make matrix, apenas os códigos que foram alterados desde a última compilação é que serão recompilados. A sintaxe é a seguinte: <destino>: <ficheiros necessarios> <tab><comando(s) de compilacao/linkagem> Makefiles - exemplo 19-10-2009 Física Computacional - MEFT 2009/10 P. Bicudo & P. Martins 10