Сетери и гетери, Конструктор

Сетерите (setters) и гетерите (getters) се клучни алатки за енкапсулација во C++. Со нив, податоците во класата ги чуваме како private (за да бидат заштитени), а до нив пристапуваме преку public методи.

Ова ни овозможува да контролираме како се менуваат вредностите

Пример за класа Student

Еве едноставен пример како се користи овој концепт:

#include <iostream> #include <string> using namespace std; class Student { private: string name; int age; public: // Сетер за име - го менува приватното поле void setName(string n) { name = n; } // Гетер за име - го враќа приватното поле string getName() { return name; } // Сетер со валидација - спречува нелогични податоци void setAge(int a) { if (a > 0) { age = a; } else { cout << "Грешка: Возраста мора да биде позитивен број!\n"; } } // Гетер за возраст int getAge() { return age; } }; int main() { Student s1; s1.setName("Марко"); s1.setAge(20); cout << "Студент: " << s1.getName() << ", Возраст: " << s1.getAge() << std::endl; return 0; }

Можност корисникот да внесува податоци преку тастатура

#include <iostream> #include <string> using namespace std; class Student { private: string name; int age; public: // Сетер за име void setName(string n) { name = n; } // Гетер за име string getName() { return name; } void setAge(int a) { if (a > 0) { age = a; } else { cout << "Greshka: Vozrasta mora da bide pozitiven broj!\n"; } } int getAge() { return age;} }; int main() { Student s1; string ime; int vozrast; cout << "Vnesete ime i prezime na studentot: "; getline(cin, ime); cout << "vnesete vozrast: "; cin >> vozrast; s1.setName(ime); s1.setAge(vozrast); cout << "\nStudent: " << s1.getName() << ", Vozrast: " << s1.getAge() << endl; return 0; }







Конструктор 

 Кога додаваме конструктор, ја правиме класата покомплетна бидејќи овозможуваме објектот да се иницијализира со вредности веднаш штом ќе биде креиран.

Еве еден пример со класа Student каде користиме:
  • Конструктор (за почетни вредности).
  • Сетери (за промена на податоците со проверка).
  • Гетери (за читање на податоците).

#include <iostream>
#include <string>
using namespace std;
class Student {
private:
    string ime;
    int indeks;
    double prosek;
public:
    // КОНСТРУКТОР - Се повикува автоматски при креирање на објектот
    Student(string i, int ind, double p) {
        ime = i;
        indeks = ind;
        // Користиме сетер внатре во конструкторот за да ја провериме валидноста
        setProsek(p);  }

    // СЕТЕРИ (Setters)
    void setIme(string i) {
        ime = i;  }

    void setProsek(double p) {
        if (p >= 6.0 && p <= 10.0) {
            prosek = p;
        } else {
            cout << "Greska: Nevaliden podatok (mora da e pomegu 6 i 10). " << endl;
            prosek = 6.0;
        }    }

    // ГЕТЕРИ (Getters)
  string getIme() { return ime; }
    int getIndeks() { return indeks; }
    double getProsek() { return prosek; }
    // Метод за приказ на информации
    void pecati() {
      cout << "Student: " << ime << " (Indeks: " << indeks << ") - Prosek: " << prosek << endl;
    }
};

int main() {
    // Креирање објект преку конструкторот
    Student s1("Marko Markovski", 201045, 9.2);
    s1.pecati();
    // Обид за внесување невалиден просек преку сетер
    cout << "\nObid da postavime prosek 15.0..." << endl;
    s1.setProsek(15.0);
        // Промена на име преку сетер
    s1.setIme("Marko S. Markovski");
    cout << "\nAzurirani podatoci:" << std::endl;
    cout << "Ime na student: " << s1.getIme() << endl;
    cout << "Finalen Prosek: " << s1.getProsek() << endl;
    return 0;
}
Задача : Во претходниот пример поставете можност внесот на податоци да се врши преку тастатура 

Наједноставно кажано: Конструкторот е „рецептот“ за тоа како се раѓа еден објект.

Еве ги 3-те клучни правила за конструктор:

  1. Името на конструкторот мора да биде идентично со името на класата.

  2. Нема тип на враќање (не пишуваме ни void, ни int, ништо).

  3. Се повикува автоматски само еднаш — во моментот кога пишуваме Student s1;

Зошто воопшто ни е потребен?

Замисли да правиш објект Student. Ако немаш конструктор, компјутерот ќе резервира меморија, но во променливите ime и indeks ќе има „ѓубре“ (случајни броеви преостанати во меморијата). Конструкторот гарантира дека објектот ќе почне со чисти и точни податоци.

#include <iostream>
#include <string>
using namespace std;

class Student {
public:
string ime;
int indeks;
// 1. Празен конструктор (Default Constructor)
// Ова се случува ако само напишеш: Student s;
Student() {
ime = "Непознато";
indeks = 0;
cout << "Нов студент!" << endl;
}

// 2. Конструктор со параметри
// Ова се случува ако напишеш: Student s("Ана", 123);
Student(string i, int ind) {
ime = i;
indeks = ind;
cout << "Нов студент " << ime << "!" << endl;
} };

int main() {
// Тука автоматски се повикува првиот (празниот) конструктор
Student s1;
// s1.ime сега е "Непознато"
// Тука автоматски се повикува вториот конструктор со вредности
Student s2("Марко", 21105);
// s2.ime сега е "Марко"
return 0;
}

  • Конструкторот е како моментот кога во фабрика го склопуваат телефонот и му ставаат сериски број. Тоа се прави само еднаш.

  • Сетерот е како кога ти подоцна ќе го смениш името на телефонот во менито за Settings. Тоа можеш да го правиш колку пати сакаш.

  • Што треба да запомниш (накратко):

    1. Конструкторот е „Раѓање“: Без него, објектот не знае кој е и што има. Тој ги поставува почетните вредности. /создава и иницијализира објект

    2. Сетерот е „Промена“: Тој дозволува безбедно да ја смениш вредноста (на пр. да додадеш пари на сметката) откако објектот веќе е создаден. /менува вредности после создавање

    3. Гестерот е „Поглед“: Тој само ти кажува колку е вредноста, без да ја менува.

    #include <iostream>
    #include <string>
    using namespace std;
    class BankarskaSmetka {
    private:
        string sopstvenik;
        double balans;
    public:
        // 1. КОНСТРУКТОР: Се извршува САМО КОГА СЕ КРЕИРА СМЕТКАТА
        // Ова е моментот кога клиентот доаѓа во банка и ја отвора сметката.
        BankarskaSmetka(string ime, double pocetenVlog) {
            sopstvenik = ime;
            if (pocetenVlog >= 0) {
                balans = pocetenVlog;}
                else {
                balans = 0; } // Не може да отвори сметка со негативни пари
            
            cout << "--- Smetkata za " << sopstvenik << " e uspeshno kreirana! ---" << endl;
        }
        // 2. СЕТЕР: Се извршува секогаш кога клиентот сака да стави пари
        void uplati(double suma) {
            if (suma > 0) {
                balans += suma;
            cout << "Uspeshna uplata od " << suma << " denari." << endl;
            }      }
        // 3. ГЕТЕР: Се извршува кога клиентот сака да провери колку пари има
        double getBalans() {
            return balans;
        } };

    int main() {
        // ТУКА СЕ ПОВИКУВА КОНСТРУКТОРОТ (еднаш)
        BankarskaSmetka smetka1("Petar", 1000.0);
        // Проверуваме состојба преку ГЕТЕР
        cout << "Momentalna sostojba: " << smetka1.getBalans() << " den." << endl;
        // Менуваме состојба преку СЕТЕР (уплата)
        smetka1.uplati(500.0);
        // Повторно проверуваме преку ГЕТЕР
        cout << "Nova sostojba: " << smetka1.getBalans() << " den." << endl;
        return 0;
    }

    Корисникот внесува податоци преку тастатура 

    #include <iostream>
    #include <string>
    using namespace std;

    class BankarskaSmetka {
    private:
        string sopstvenik;
        double balans;
    public:
        BankarskaSmetka(string ime, double pocetenVlog) {
            sopstvenik = ime;
            if (pocetenVlog >= 0)
                balans = pocetenVlog;
            else
                balans = 0;
            cout << "--- Smetkata za " << sopstvenik << " e uspeshno kreirana! ---" << endl;
        }
        void uplati(double suma) {
            if (suma > 0) {
                balans += suma;
                cout << "Uspeshna uplata od " << suma << " denari." << endl;
            }     }

        double getBalans() {
            return balans;     }
    };

    int main() {
        string ime;
        double pocetenVlog;
        double uplata;
        cout << "Vnesi ime na sopstvenik: ";
        cin >> ime;
        cout << "Vnesi poceten vlog: ";
        cin >> pocetenVlog;
        BankarskaSmetka smetka1(ime, pocetenVlog);
        cout << "Momentalna sostojba: " << smetka1.getBalans() << " den." << endl;
        cout << "Vnesi suma za uplata: ";
        cin >> uplata;
        smetka1.uplati(uplata);
        cout << "Nova sostojba: " << smetka1.getBalans() << " den." << endl;
        return 0;
    }

    ПРАШАЊА 

    Што претставува „класата“ во програмирањето?

    А) Конкретен предмет во меморијата
    Б) Шаблон (blueprint) според кој се креираат објекти.
    В) Функција која враќа само броеви.

    Бонус задача: Напиши ја основната синтакса за дефинирање класа со име Avtomobil

    Кој модификатор за пристап оневозможува директен пристап до податоците надвор од класата?

    А) public
    Б) protected
    В) private

    Која е главната цел на конструкторот?

    А) Да го избрише објектот од меморијата.
    Б) Да ги постави почетните вредности на атрибутите при креирање на објектот.
    В) Да врши пресметки и да печати резултати во конзола.

    Зошто користиме „сетер“ (setter) наместо директно да ја менуваме променливата?

    А) Затоа што кодот изгледа поубаво.
    Б) За да додадеме логика за валидација (напр. да провериме дали возраста е позитивен број).
    В) Сетерите се задолжителни за програмата да работи.


    Напиши програма со следните барања
    Класата да има два приватни броја (a и b).
    Да има конструктор кој ќе ги прими тие броеви од корисникот.
    Да има методи (функции) за собирање и множење.
    Додади нов метод за одземање на двата броја 
    Решение 
    #include <iostream>
    using namespace std;
    class Kalkulator {
        private:
            double br1;
            double br2;
        public:
            // Конструктор кој ги поставува броевите
            Kalkulator(double a, double b) {
                br1 = a;
                br2 = b;
            }
            // Метод за собирање
            void soberi() {
                cout << "Збирот е: " << br1 + br2 << endl;
            }
            // Метод за множење
            void pomnozi() {
                cout << "Производот е: " << br1 * br2 << endl;
            }
    };

    int main() {
        double x, y;
        // Внесување од тастатура
        cout << "Внесете го првиот број: ";
        cin >> x;
        cout << "Внесете го вториот број: ";
        cin >> y;
        // Креирање на објектот со внесените вредности
        Kalkulator mojKalkulator(x, y);
        // Повикување на методите
        mojKalkulator.soberi();
        mojKalkulator.pomnozi();
        return 0;
    }




    #include <iostream>
    using namespace std;
    class podatok {
    private:
       double x, y; // Реални приватни податоци
    public:
        // Конструктор со подразбирливи вредности 0.0
        podatok(double a = 0.0, double b = 0.0) {
            x = a;
            y = b;
        }
        // Inline функција дефинирана во самата класа
        void srednaV() {
            double rezultat = (x + y) / 2.0;
            cout << "Srednata vrednost na " << x << " i " << y << " e: " << rezultat << endl;     }
    };

    int main() {
        // Декларирање објект P со вредности 10 и 5
        podatok P(10, 5);
        // Повикување на функцијата за средна вредност
        P.srednaV();
        return 0;
    }

    ________________________________________________________________

    #include <iostream>
    using namespace std;
    class Presmetka {
    private:
        int n; // Приватна членка
    public:
        // Сетeр - овозможува поставување или промена на вредноста на n
        void setN(int vrednost) {
            if (vrednost >= 0) {
                n = vrednost;
            } else {
                cout << "Greska: n mora da bide nenegativen broj!" << endl;
                n = 0;          }
        }
        // Гетер - овозможува читање на вредноста на n надвор од класата
        int getN() {
            return n;      }
        // Функција за пресметување на производот
        long long presmetajProizvod() {
            if (n == 0) return 0; // Првите 0 природни броеви немаат производ
            long long proizvod = 1;
            for (int i = 1; i <= n; i++) {
                proizvod *= i;
            }
            return proizvod;      }
    };

    int main() {
        Presmetka objekt; // Креирање објект
        int n;
        cout << "Vnesi go brojot n: ";
        cin >> n;
        // Го користиме сетерот за да ја внесеме вредноста
        objekt.setN(n);
        // Го користиме гетерот за да ја прикажеме вредноста и го повикуваме методот
        cout << "Za n = " << objekt.getN() << ", proizvodot e: " 
             << objekt.presmetajProizvod() << endl;
        return 0;
    }

    No comments: