Menu
Coddy logo textTech

İç İçe ve Dahili Sınıflar

Coddy'nin C++ Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası — ders 38 / 104.

Bir iç içe sınıf (nested class), başka bir sınıfın içinde tanımlanan bir sınıftır. Bu teknik, ilgili türleri bir araya getirerek kodu düzenlemeye yardımcı olur ve uygulama ayrıntılarını gizleyerek kapsüllemeyi (encapsulation) artırabilir.

class LinkedList {
public:
    class Node {    // İç içe geçmiş sınıf
        int data;
        Node* next;
    public:
        Node(int d) : data(d), next(nullptr) {}
        friend class LinkedList;
    };
    
private:
    Node* head;
    
public:
    LinkedList() : head(nullptr) {}
};

Yuvalanmış Node sınıfı, LinkedList sınıfına sıkı sıkıya bağlıdır; sadece bu bağlamda anlamlıdır. Onu iç içe yerleştirerek bu ilişkiyi belirtiriz ve küresel ad alanını "Node" gibi genel bir isimle kirletmekten kaçınırız.

İç içe sınıflar, öğrendiğiniz aynı erişim kurallarını takip eder. Private bölümünde bildirilen bir iç içe sınıfa yalnızca dış sınıf içinden erişilebilir.

public olarak bildirildiğinde, harici kod onu kapsam operatörü ile kullanabilir:

LinkedList::Node node(42);    // Sadece Node public ise

Yönle ilgili önemli bir ayrıntı: iç içe geçmiş bir sınıf (nested class), kapsayan sınıfın (enclosing class) bir üyesidir ve diğer tüm üyelerle aynı erişim haklarına sahiptir; bu nedenle, herhangi bir friend bildirimi olmadan kapsayan sınıfın özel (private) üyelerine erişebilir. Ancak bunun tersi otomatik değildir; kapsayan sınıf, iç içe geçmiş sınıfın özel (private) üyelerine erişim hakkına sahip değildir.

Bu yüzden yukarıdaki örnekte Node, friend class LinkedList; bildiriminde bulunur: friend bildirimi, kapsayan LinkedList sınıfına Node'un özel (private) üyelerine erişim yetkisi verir; bu, otomatik olmayan tek yöndür.

challenge icon

Görev

Kolay

Görevlerin bir proje içinde organize edildiği basit bir görev yönetim sistemi kuralım. Bu, iç içe geçmiş sınıflar (nested classes) için mükemmel bir senaryodur — bir Task sadece bir Project bağlamında anlamlıdır, bu nedenle kodumuzu düzenli tutmak ve global ad alanını kirletmemek için onu içeriye yerleştireceğiz.

Kodunuzu düzenlemek için iki dosya oluşturacaksınız:

  • Project.h: İç içe geçmiş bir Task sınıfı içeren bir Project sınıfı tanımlayın.

    İç içe geçmiş Task sınıfınız, dışarıdan erişilebilmesi için Project sınıfının public bölümünde bildirilmelidir. Bir görev adını (string) ve bir tamamlanma durumunu (bool) saklamalıdır. Ona adı alan ve görevi varsayılan olarak tamamlanmamış olarak ayarlayan bir yapıcı (constructor) verin. Görevi tamamlandı olarak işaretlemek için complete(), durumunu kontrol etmek için isComplete() ve adı almak için getName() metotlarını ekleyin.

    Project sınıfının kendisi bir proje adını (string) ve bir Task işaretçileri koleksiyonunu saklamalıdır. Proje adını alan bir yapıcı, yeni bir görev oluşturan ve projeye ekleyen bir addTask(const std::string& taskName) metodu, bir görevi ismine göre bulup tamamlayan bir completeTask(const std::string& taskName) metodu ve proje adını ve ardından her görevin durumunu gösteren bir displayStatus() metodu sağlayın.

    Task, Project içinde iç içe geçtiği için, Project sınıfı görevlerle doğrudan çalışabilir. Yıkıcıda (destructor) dinamik olarak ayrılmış görevleri temizlemeyi unutmayın.

  • main.cpp: Girişten bir proje adı ve iki görev adı okuyarak (toplam üç satır) her şeyi bir araya getirin. Verilen adla bir Project oluşturun, her iki görevi de ona ekleyin ve ardından başlangıç durumunu görüntüleyin. İlk görevi tamamlayın ve değişikliği göstermek için durumu tekrar görüntüleyin.

    displayStatus() için çıktı formatı şu şekilde olmalıdır:

    Project: <project_name>
      - <task_name>: [incomplete]
      - <task_name>: [complete]

    Her görevin durumuna göre [complete] veya [incomplete] kullanın.

Bu meydan okuma, iç içe geçmiş sınıfların ilgili türleri düzenlemeye nasıl yardımcı olduğunu gösterir — Task sınıfı Project sınıfına sıkı sıkıya bağlıdır ve tek başına bir anlam ifade etmez. Onu iç içe yerleştirerek, kod yapımızda bu ilişkiyi net bir şekilde belirtmiş oluruz.

Kendin dene

#include <iostream>
#include <string>
#include "Project.h"

using namespace std;

int main() {
    // Girdiyi oku
    string projectName;
    string task1Name;
    string task2Name;
    
    getline(cin, projectName);
    getline(cin, task1Name);
    getline(cin, task2Name);
    
    // TODO: Verilen isimle bir Proje (Project) oluşturun
    
    // TODO: Her iki görevi de projeye ekleyin
    
    // TODO: Başlangıç durumunu görüntüleyin
    
    // TODO: İlk görevi tamamlayın
    
    // TODO: Değişikliği göstermek için durumu tekrar görüntüleyin
    
    return 0;
}
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler