Məzmuna keç
Educora
Orta20 dəq8 / 10

Varislik və polimorfizm

Mövcud sinifdən yeni sinif törət, `virtual` funksiyalar və `override` ilə polimorfizm qur, abstrakt siniflərdən istifadə et.

Özünü yoxla
Bu dərsdə öyrənəcəksən
  • Baza sinifdən törəmə sinif yaratmaq və baza konstruktorunu çağırmaq
  • virtual və override ilə metodları yenidən təyin etmək
  • Polimorfizmin baza göstəricisi və istinadı vasitəsilə necə işlədiyini izah etmək
  • Təmiz virtual funksiyalarla abstrakt sinif yaratmaq

Oyunda döyüşçü, sehrbaz və oxatan var. Onların hamısının adı və canı var, hamısı hücum edir — amma hər biri öz üsulu ilə. Eyni kodu üç sinifdə təkrarlamaq əvəzinə ümumi hissəni bir baza sinifdə yazıb, fərqləri törəmə siniflərə vermək olar. Bu, varislikdir. Polimorfizm isə sənə hamısına eyni cür müraciət etməyə imkan verir: «hücum et!» deyirsən, hər personaj özünə uyğun hücum edir.

Varislik

class Warrior : public Character yazılışı «Warrior Character-dən törəyir» deməkdir. Törəmə sinif baza sinfin bütün üzvlərini alır və öz üzvlərini əlavə edə bilər. Baza sinfin protected üzvləri kənar koda bağlıdır, amma törəmə siniflər onları görür. Törəmə sinfin konstruktoru baza konstruktorunu inisializasiya siyahısında çağırır.

C++
#include <iostream>
#include <string>

class Character {
public:
    Character(const std::string& name, int health)
        : name_(name), health_(health) {}

    void status() const {
        std::cout << name_ << " has " << health_ << " HP\n";
    }

protected:
    std::string name_;
    int health_;
};

class Warrior : public Character {
public:
    Warrior(const std::string& name) : Character(name, 150) {}

    void shieldUp() {
        health_ += 20;
        std::cout << name_ << " raises a shield\n";
    }
};

int main() {
    Warrior w("Elvin");
    w.status();
    w.shieldUp();
    w.status();
    return 0;
}
Gözlənilən nəticə
Elvin has 150 HP
Elvin raises a shield
Elvin has 170 HP
status() baza sinifdən hazır gəlir, shieldUp() isə yalnız Warrior-da var.

Virtual funksiyalar

Törəmə obyektə baza sinfin istinadı və ya göstəricisi ilə müraciət etmək olar: hər döyüşçü həm də personajdır. Bəs belə müraciətdə hansı metod çağırılır? Adi metodda — baza sinfin versiyası, çünki seçim kompilyasiya zamanı istinadın tipinə görə edilir. Metod virtual elan olunubsa, seçim proqram işləyərkən obyektin həqiqi tipinə görə edilir.

C++
#include <iostream>

class Base {
public:
    virtual ~Base() = default;
    void hello() const { std::cout << "Base::hello\n"; }
    virtual void greet() const { std::cout << "Base::greet\n"; }
};

class Derived : public Base {
public:
    void hello() const { std::cout << "Derived::hello\n"; }
    void greet() const override { std::cout << "Derived::greet\n"; }
};

int main() {
    Derived d;
    const Base& ref = d;
    ref.hello();
    ref.greet();
    return 0;
}
Gözlənilən nəticə
Base::hello
Derived::greet
hello virtual deyil — istinadın tipi (Base) qərar verir; greet virtualdır — obyektin həqiqi tipi (Derived) qərar verir.

Abstrakt siniflər və polimorfizm

Bəzən baza sinif metodu necə yerinə yetirəcəyini bilmir: «fiqurun sahəsi» ümumi halda hesablanmır. Belə metod = 0 ilə təmiz virtual elan olunur. Ən azı bir təmiz virtual metodu olan sinif abstraktdır: ondan obyekt yaratmaq olmaz, yalnız törəmək olar. Sonra müxtəlif fiqurları bir vektorda saxlayıb onlarla eyni cür işləyə bilərik:

C++
#include <iostream>
#include <memory>
#include <vector>

class Shape {
public:
    virtual ~Shape() = default;
    virtual int area() const = 0;
};

class Rect : public Shape {
public:
    Rect(int w, int h) : w_(w), h_(h) {}
    int area() const override { return w_ * h_; }
private:
    int w_, h_;
};

class Triangle : public Shape {
public:
    Triangle(int b, int h) : b_(b), h_(h) {}
    int area() const override { return b_ * h_ / 2; }
private:
    int b_, h_;
};

int main() {
    std::vector<std::unique_ptr<Shape>> shapes;
    shapes.push_back(std::make_unique<Rect>(4, 3));
    shapes.push_back(std::make_unique<Triangle>(6, 5));
    int total = 0;
    for (const auto& s : shapes) {
        std::cout << "Area: " << s->area() << '\n';
        total += s->area();
    }
    std::cout << "Total: " << total << '\n';
    return 0;
}
Gözlənilən nəticə
Area: 12
Area: 15
Total: 27
Dövr Shape-in hansı növ olduğunu bilmir, amma hər obyekt öz area() metodunu çağırır — bu, polimorfizmdir.
TerminMənası
baza sinifümumi hissəni saxlayan sinif (Shape)
törəmə sinifbazadan törəyib onu genişləndirən sinif (Rect)
virtualmetod obyektin həqiqi tipinə görə seçilir
overridevirtual metodun yenidən təyin olunduğunu yoxlatdırır
= 0təmiz virtual metod; sinif abstrakt olur

Əsas fikirlər

  • class B : public A — B A-dan törəyir və onun üzvlərini alır.
  • protected üzvləri törəmə siniflər görür, kənar kod isə görmür.
  • virtual metod baza istinadı və ya göstəricisi ilə çağırılanda obyektin həqiqi tipinə görə seçilir.
  • override səhvləri kompilyasiya zamanı tutur; polimorf bazanın destruktoru virtual olmalıdır.
  • = 0 olan təmiz virtual metod sinfi abstrakt edir: ondan obyekt yaratmaq olmur.

Özünü yoxla

10 sual. Hər düzgün cavab XP qazandırır.

1 / 10
Archer sinfini Character-dən necə törətmək olar?