C++/Funcións

En Galilibros, o Wikibooks en galego.
< C++
C++
Funcións


Unha función é un anaco de código fonte que ten nome, e que pode chamarse dende outras partes do código. A definición dunha función segue a seguinte sintaxe:

«tipo de dato do resultado» «nome da función»(«lista de parámetros»)
{
  «Sentenzas que conforman a función»
}

Un exemplo da definición dunha función podería ser a seguinte:

int funcion(char caracter, int numero)
{
  if(caracter == 'a')
    return numero * 2;
  else
    return numero * numero;
}

Función principal[editar]

Todo programa en C++ debe conter unha función chamada «main». Ao executarse o programa, será esta a función que se execute.

A función principal ten que devolver un valor enteiro. Este valor indicará se o programa se executou correctamente ou, de haber algún erro, para indicar o tipo de erro. Se o valor devolto é cero significará que o programa rematou a súa execución correctamente, mentres que se é distinto de cero significará que houbo algún tipo de erro.

A función principal é a única función na que non fai falla escribir explícitamente a sentenza de devolución, pero recoméndase facelo de todos xeitos.

Funcións membro[editar]

As funcións membro, tamén coñecidas como “métodos” —aínda que prefírese empregar a denominación principal—, son aquelas que forman parte (son membro) dunha clase.

Encadeamento de métodos[editar]

O encadeamento de métodos é unha práctica que consiste en executar unha función membro sobre un obxecto que devolve á súa vez un obxecto, e executar seguidamente unha función membro sobre o obxecto devolto pola primeira función.

En código, o aspecto dun encadeamento de métodos sería o seguinte:

obxecto.funcionmembro1().funcionmembro2();

O primeiro en executarse sería obxecto.funcionmembro1(). Esta función devolvería un obxecto, ben unha referencia ao propio obxecto, ben outro obxecto calquera. Chámalle obxectoX. obxectoX pasa a ser entón o obxecto this da función funcionmembro2()

Un exemplo claro do uso do encadeamento de métodos pode verse no uso da biblioteca iostream. O código cout << a << b funciona grazas a que a función cout << a devolve o propio obxecto cout.

Outro uso non tan habitual pero máis mañoso do encadeamento de métodos é o modismo dos parámetros con nome.

Funcións membro puramente virtuais[editar]

Son declaracións de funcións que fan que unha clase pase a ser abstracta —como é o caso das clases base abstractas—. Normalmente, a definición só se inclúe nas clases derivadas.

A sintaxe básica das funcións membro puramente virtuais é a seguinte:

 class Clase {
 public:
   virtual void funcion() const = 0;  // «= 0» dá o matiz de «puramente virtual».
   // [...]
 };
Nota: pódese fornecer unha definición para as funcións puramente virtuais, pero á xente sen moita experiencia isto pode resultarlles confuso, polo que mellor farán en evitalo.

Funcións substitutas[editar]

As funcións substitutas son aquelas para as que o compilador substitúe as chamadas polo código da definición. Por exemplo, o compilador convertería o seguinte código:

inline int sumar(int sumando1, int sumando2) {
  return sumando1 + sumando2;
}

main() {
  int a, b, c;
  a = sumar(b,c);
}

Nestoutro:

main() {
  int a, b, c;
  a = b + c;
}

Conceptualmente trátase de algo similar ao que se fai con #define.

En calquera caso, cómpre saber que o compilador pode perfectamente ignorar esta calidade das funcións. É dicir, o compilador pode substituír todas as funcións substitutas, só algunhas, ou mesmo ningunha. Esta flexibilidade, malia o que poida parecer, é unha grande vantaxe.

Designar funcións substitutas[editar]

A declaración da función substituta non é distinta da de calquera outra función. A parte que cambia é a da definición. Ao definir unha función substituta, debe prefixarse coa palabra clave inline, e a definición debe estar nun ficheiro de cabeceira.

Funcionamento da substitución[editar]

Para entendermos mellor a utilidade deste tipo de funcións, nada como vermos un exemplo. Considérese a seguinte chamada á función funcion():

void main() {
  int x, y, z;
  // Código que fai uso das tres variables.
  funcion(x, y, z);
  // Máis código que emprega as variables.
}

Partindo da base dunha aplicación de C++ típica con rexistros e rima (stack), os rexistros e parámetros escríbense na rima xusto antes da chamada a funcion(), logo dende funcion() lense os parámetros da rima, e vólvense ler para restablecer os rexistros cando funcion() volve a main(). Pero trátase de moitos procesos de lectura e escritura innecesarios, especialmente nos casos en que o compilador pode empregar rexistros para as tres variables, nos que as variables se escribirían dúas veces (como rexistro e como parámetro) e se lerían outras tantas (ao empregalas dentro de funcion() e para restablecer os rexistros na devolución a main()).

Se o compilador substitúe a chamada polo código da definición, poderían aforrarse todas esas operacións. Ao non haber unha chamada a unha función, non habería necesidade ningunha de tocar os rexistros, e como os parámetros xa están no rexistro, non habería necesidade de ler ou escribir os parámetros.

Por suposto, isto non ten por que ocorrer deste xeito, e existen moitas circunstancias que condicionan o que ocorra en realidade ante situacións similares.

Mellora do rendemento[editar]

O uso de funcións substitutas pode mellorar o rendemento, empeoralo, ou non afectar a este de xeito algún. E que ocorra unha cousa ou a outra depende de tantos factores que a única maneira de estar seguro de cal foi o resultado e probar a empregar as funcións das dúas formas, e comprobalo[1].

Uso dentro de clases[editar]

As funcións substitutas poden empregarse dentro de clases. Isto supón contar coas vantaxes de capsular e coa velocidade do acceso directo.

Cando usar #define e cando funcións substitutas[editar]

Cómpre evitar os #define sempre que non haxa unha boa razón para empregalos, e rara vez haberá tal razón. As funcións substitutas son superiores aos #define en practicamente todos os aspectos.

Pero cómpre tamén non esquecer que os #define están aí, e pode que nalgunha (remota) situación o seu uso sexa preferible ao das funcións substitutas.

Notas[editar]

  1. «Melloran as funcións substitutas o rendemento?», Respostas a preguntas habituais sobre C++ (en inglés).


C++
Funcións