Програмен език C++
Част 24
.
За функциите на класовете и малко повече
.
(съдържание)
.
Функция е именована последователност от твърдения (statements), която може да се извика с дадени аргументи и може да връща стойност. Обикновено, в изпълнимия компютърен код на програмата (т.н. executable file) се отделя само едно място за кода на функцията. При всяко едно извикване на функцията програмата се обръща към този код, прехвърля стойностите на параметрите на функцията (ако има такива), изпълнява поредицата от твърдения във функцията и се връща след мястото в основната програма, където е извикана функцията, като при това ако е необходимо, връща и стойност от функцията. По този начин кодът на изпълнимия файл съдържа кода на функцията само на едно място, независимо колко пъти има обръщение към нея в програма. Така се спестява памет, особено за големи по код функции. Но всичко това изисква процесорно време и ако една, например малка по код функция се среща на много места в програма или е извиквана, например, в цикъл, то времето за изпълнението на програмата се увеличава значително. За да се избегне това забавяне може функцията да се дефинира като инлайн функция (inline function).

1. Инлайн функции (Inline Functions). Една инлайн функция се специфицира с ключовата дума inline по следния начин

inline void func()
{
   // statements
}

или ако само се декларира функцията, се пише

inline void func();  // declaration

Извикването на функцията се извършва по обичайния начин:

func();

Обикновено като инлайн функции се дефинират (декларират) къси функции, които се извикват много често в програмата, особено тези извиквани в цикли. На английски това се нарича to inline a function. Ако функцията има голям машинен код, дефинирането и като инлайн функция ще увеличи значително обема на изпълнимия код. На практика много рядко е необходимо потребителят да се грижи за инлайн функциите, защото самият компилатор преценява и прави някои функции такива.

2. Функции на класа, дефинирани в класа (Member Functions Defined Within a Class). Дефиницията на една функция в класа я прави по подразбиране инлайн функция, т.е. те са такива, независимо дали програмистът ги е написал с ключовата дума inline. Да напомним, че функциите дефинирани в класа са функции, чието тяло е в класа, като например следната функция от лекция 16 на класа employee.

 void output()        // display employee data
 {
   cout << "   Name = ";

   for (int j = 0; j < n; ++j) // display one character
     cout << name[j];         // at a time
   cout << "\n   Serial number = " << serial_number;
 }

Обикновените функции не са инлайн, освен ако програмиста не ги специфицира така с ключовата дума inline.

3. Функции на класа, дефинирани извън класа (Member Functions Defined Outside a Class). Ако искате някоя голяма по код функция на класа да не е инлайн, то трябва да я декларирате в класа и след това да я дефинирате извън класа. Например

class anyClass           // class specification
{
  public:
    void anyfunc();      // declaration only
};                       // еха до class specification

void anyClass::anyfunc() // definition outside class
{                        // this function is NOT inline
   // statements
}

При дефиницията е използван операторът ::, който на английски се нарича Scope Resolution Operator и чийто тромав български превод e оператор за решение за обхвата - вижте дефиницията на обхват - scope. Той е необходим на компилатора, за да разбере функцията на кой клас е, защото тя е написана извън големите скоби на класа.

Както споменахме, така дефинираните функции не са инлайн по подразбиране (by default), но вие въпреки това може да изискате от компилатора да ги направи такива ако използвате ключовата дума inline.

! И в двата случая - на дефиниране на функция в класа и на дефиниране на функция извън класа но с ключовата дума inline при декларацията, което ги прави инлайн функции по подразбиране, компилаторът може да откаже те да бъдат такива. Например, ако има цикли в обявените инлайн функции.

4. Демонстрационна програма. Това е изменена версия на програмата complex3.cpp от лекция 17. в която версия три от функциите на класа compl_num са изнесени извън класа. Обърнете внимание на доста объркващия правопис при дефиницията на третата функция:

complex_number complex_number::root_compl_num(int m, int n)

Повтарянето на два пъти на името на класа се дължи на факта, че функцията връща стойност от типа на класа и че функцията е от този клас (вторият път името на класа е написано преди оператора ::).

// complex4.cpp
// a class that models a complex number data type
// use is made of Member Functions Defined Outside a Class

#include <iostream.h>
#include <conio.h>               //for getche()
#include <math.h>               //for getche()

class complex_number
{
  private:
    float real;       // real part
    float imaginary;  // imaginery part
    float abs;        // absolute value
    float arg;        // argument
  public:
    void set()
    {
      char dummy;        // for comma
      float a, b;

      cout << "Press i for Re + Im*j or press e for Abs*e^Arg: ";
      dummy = getche();
      if (dummy == 'i')
      {
        cout << "\nEnter Re: ";
        cin >> real;

        cout << "Enter Im: ";
        cin >> imaginary;

        abs = sqrt(real*real + imaginary*imaginary);
        if (real != 0)
          if (real > 0)
            arg = atan(imaginary/real);
          else
            arg = atan(imaginary/real) + M_PI;
        else
          if (real > 0)
            arg = M_PI/2;
          else
            arg = -M_PI/2;
      }
      else
      {
        cout << "\nEnter Abs: ";
        cin >> abs;

        cout << "Enter Arg: ";
        cin >> arg;

        real = abs*cos(arg);
        imaginary = abs*sin(arg);
      }
    }  // void set()

    void display()
    {
      cout << '('
           << real       // real part
           << " , "
           << imaginary  // imaginary part
           << ')';
      cout << " ["
           << abs       // real part
           << " * e( i*"
           << arg  // imaginary part
           << " ) ]";
    }

    void add(complex_number compl_num);
 

    void mult(complex_number compl_num);

    complex_number root_compl_num(int m, int n);

};  // class complex_number

void complex_number::add(complex_number compl_num)
{
  real += compl_num.real;
  imaginary += compl_num.imaginary;
}

void complex_number::mult(complex_number compl_num)
{
  complex_number cn;
  cn.real = real;
  cn.imaginary = imaginary;

  real = cn.real*compl_num.real - compl_num.imaginary*cn.imaginary;
  imaginary = cn.real*compl_num.imaginary + compl_num.real*cn.imaginary;
}

complex_number complex_number::root_compl_num(int m, int n)
{
  float phase = arg / n;
  complex_number root;

  root.abs = exp(log(abs)/n);
  root.arg = phase + m*2*M_PI/n;
  root.real = root.abs*cos(root.arg);
  root.imaginary = root.abs*sin(root.arg);

  return root;
}

void main()
{
  complex_number c1, c2;       // create a complex_number variable
  complex_number c_roots[20];  // create an array of 20 complex_number variable
  int n;

  // enter c1
  cout << "For c1, ";
  c1.set();       // set c1

  // show the addition result
  cout << "\nc1 = ";
  c1.display();   // display c2

  // show the addition result
  cout << "\nEnter root (n <= 20):";
  cin >> n;   // display c2

  cout << "\n=== The " << n << "th roots are ===\n";

  // find n roots of c1
  for (int i = 0; i < n; i++)
  {
    c_roots[i] = c1.root_compl_num(i, n);
  }

  // display n roots of c1
  for (int i = 0; i < n; i++)
  {
    // show the i-th root
    cout << "\nroot[" << i + 1 << "] = ";
    c_roots[i].display();           // display c_root[i]
  }

  // stop the flow on the monitor
  getch();

}  //end main

.
(съдържание)
.
Литература
.
[1] Robert Lafore; C++ Interactive Course. Waite Group Press, Macmillan Computer Publishing, 1996.
.
Автор: Проф. Процесор Аритметиков
.
[ това е материал от брой 25 от ноември 2008 г. на списание "Коснос" www.kosnos.com ]

Keywords: С++,  OOP programming , C++ , Classes , Inheritance , Reusability , Creating New Data Types , Polymorphism and Overloading
Ключови думи: клас , обект, обектно ориентирано програмиране , полиморфизъм switch if else ?