Пријатели на класа

Концепт и дефиниција за пријателите на класа


    Честопати е добро да се дизајнира класа така што таа исто така има „привилегирани“ корисници или функции или други класи што имаат право на пристап до нејзините приватни членови. Таквите функции и часови се нарекуваат пријатели.

Пријателски функции
 

    Пријателските функциите се функции кои не се членови на класа, но имаат пристап до приватни членови на класата. Овие функции можат да бидат глобални функции или членови на други класи.
За да може функцијата да биде прогласена за пријател на класа, потребно е да се наведе декларацијата за таа функција во декларацијата за таа класа со клучниот збор пријател friend пред неа.

Пријателската функција е дефинирана на следниот  начин:
пријателска глобална функција:

friend tip ime_funkcija(argumenti)
{telo funkcija};


пријателски член на друга класа:

friend tip ime_klasa::ime_funkcija(argumenti);

    Глобалните функции кои претставуваат услуги од класа или операции на таа класа (обично пријатели од таа класа) се нарекуваат класни услуги.
   
Нема формална причина да се користи глобалната (обично пријателска) функција наместо функцијата член.

    Постојат моменти кога глобалните (пријателски) функции се попогодни:

    - кога некоја функција треба да пристапи до членови на повеќе класи, пријателската глобална функција е поефикасна;
    - понекогаш е поудобно да се користат глобални функции (повикот е f (x)) отколку членовите (повикот е x.f ()); на пример, макс (а, б) е повеќе читлив од а.макс (б);
    - кога операторите се преклопуваат, често е полесно да се дефинираат глобалните (оператор) функции на една членка.
    - функцијата член мора да биде повикана за објект од дадена класа, додека објектот од друг вид може да се достави до глобалната функција, која ќе се претвори во потребниот тип;
 

    „Пријателство“ не е наследено: ако функцијата f е пријател на класа X, а класата Y е изведена (наследник) од класа X, функцијата f не е пријател на класа Y.
   
Пример за пријателска функција:

#include <iostream>

using namespace std;

 

class Rastojanie {

    private:

        int metri;

        friend int Dodadi5(Rastojanie);  // friend funkcija

    public:

        Rastojanie()  // konstruktor

        {

              metri=0;

        }

};

 

int Dodadi5(Rastojanie d)     // friend funkcija definicija

{

    d.metri += 5;   //pristap do privaten clen so friend funkcija

    return d.metri;

}

 

int main() {

    Rastojanie D;

    cout << "Rastojanie: " << Dodadi5(D);

    return 0;

}

Пријателски класи
 

    Ако од сите функции на член на класа Y се бара да бидат пријателски функции на класа X, тогаш класата Y е декларирана како пријателска класа на класа X. Тогаш сите функции на член на класа Y можат да пристапат до приватни членови од класа X, обратно не важи („пријателството“ не е симетрична врска):

class X  {

    friend class Y;    // prijatelska klasa na X
        ............

};

class Y  {

        ............

};

    „Пријателство“ не е ниту преодна врска: ако класата Y е пријател на класа X, а класата Z е пријател на класа Y, класата Z не е автоматски пријател на класа X, но таа мора да биде експлицитно нагласена (доколку е потребно )

  Пријателски класи обично се користат кога некои две класи имаат поблиски меѓусебни односи. Во исто време, непотребно е (и лошо) да се „откријат“ делови од класата, така што тие ќе бидат достапни на друга пријателска класа, бидејќи на тој начин ќе бидат достапни и за другите (се распаѓа енкапсулацијата - затвореноста на податоците). Тогаш овие две класи се прогласени за пријателски.

Пример: За собирање на два броја членови на две класи од која klasaB е пријателска класа на klasaA

#include <iostream>

using namespace std;

class KlasaB;

class KlasaA {

    private:

        int brojA;

        friend class KlasaB;

    public:

        KlasaA()

                    {brojA=12;}

};

class KlasaB {

    private:

        int brojB;

    public:

        KlasaB()

                    {brojB=1;}

    int soberi() {

        KlasaA objektA;

        return objektA.brojA + brojB;

    }

};

int main() {

    KlasaB objektB;

    cout << "Suma: " << objektB.soberi();

    return 0;

}