Menu
Coddy logo textTech

Opaque Struct Tanımlama

Coddy'nin C Journey'sinin Object Oriented Programming bölümünün bir parçası — ders 18 / 61.

Artık opak işaretçi (opaque pointer) kavramını anladığınıza göre, kalıbın nasıl tamamlanacağını görelim. Başlık dosyası bir türün var olduğunu bildirir, ancak kaynak dosya, içinde gerçekte ne olduğunu tanımladığınız yerdir.

İşte kurulumun tamamı. İlk olarak, sadece ileriye dönük bildirimi (forward declaration) içeren başlık dosyası:

// counter.h
#ifndef COUNTER_H
#define COUNTER_H

typedef struct Counter Counter;  // Tamamlanmamış tür

Counter *create_counter(int start);
void free_counter(Counter *c);

#endif

Ardından, kaynak dosyası gerçek struct tanımını içerir:

// counter.c
#include "counter.h"
#include <stdlib.h>

struct Counter {
    int value;      // Dışarıdan gizli!
    int step;
};

Counter *create_counter(int start) {
    Counter *c = malloc(sizeof(Counter));
    c->value = start;
    c->step = 1;
    return c;
}

void free_counter(Counter *c) {
    free(c);
}

Kilit nokta: struct Counter { ... } yalnızca .c dosyasında görünür. counter.h dosyasını dahil eden herhangi bir dosya Counter'ın var olduğunu bilir ancak value veya step üyelerini göremez. main.c içinde c->value yazmaya çalışmak bir derleyici hatasına neden olur—üyeler gerçekten görünmezdir.

Bu ayrım, C'deki kapsüllemenin (encapsulation) temelidir. Bir sonraki adım, getter ve setter fonksiyonları aracılığıyla kontrollü erişim sağlamaktır.

challenge icon

Görev

Kolay

Opaque pointer (mat işaretçi) desenini gösteren bir Timer modülü oluşturalım. Yapı (struct) tanımını kaynak dosyasının içinde gizleyerek, dahili üyelerini modülünüzü kullanan herhangi bir kod için tamamen görünmez hale getirme pratiği yapacaksınız.

Üç dosya oluşturacaksınız:

  • timer.h: Bu sizin genel arayüzünüzdür. Sadece bir ön bildirim (forward declaration) kullanarak opak bir Timer türü bildirin—burada struct gövdesi olmamalı! Ayrıca iki fonksiyon bildirin: create_timer (saniye için bir tamsayı alır ve bir Timer işaretçisi döndürür) ve free_timer (bir Timer işaretçisi alır ve temizlik yapar). TIMER_H sembolü ile include guard kullanın.
  • timer.c: Sırrın saklandığı yer burasıdır. İki gizli üyeye sahip gerçek struct Timer yapısını tanımlayın: int seconds ve int running (çalışıyor için 1, durduruldu için 0 kullanın). Yapıyı tahsis etmek, seconds değerini sağlanan değerle başlatmak ve running değerini 1 olarak ayarlamak için kurucu (constructor) fonksiyonunuzu uygulayın. Belleği serbest bırakmak için yıkıcı (destructor) fonksiyonu uygulayın.
  • main.c: Bir zamanlayıcı oluşturmak ve başarıyla oluşturulduğunu onaylamak için Timer modülünüzü kullanın. Yapı üyeleri gizli olduğu için onlara doğrudan erişemezsiniz—tüm mesele de bu! Sadece oluşturmayı onaylayan bir mesaj yazdırın, ardından zamanlayıcıyı serbest bırakın ve bir temizleme mesajı yazdırın.

Bir girdi alacaksınız: zamanlayıcıyı başlatmak için saniye sayısı (bir tamsayı).

Ana dosyanızda, sağlanan saniye değeriyle bir zamanlayıcı oluşturun. Bir oluşturma mesajı yazdırın, ardından zamanlayıcıyı serbest bırakın ve bir onay yazdırın.

Çıktıyı şu formatta yazdırın:

Timer created
Timer freed

Buradaki temel nokta, main.c dosyasının Timer işaretçileriyle çalışabilmesi ancak seconds veya running üyelerine doğrudan erişme yolunun olmamasıdır. main.c içinde t->seconds yazmaya çalışmak bir derleyici hatasına neden olur çünkü struct gövdesi yalnızca timer.c içinde tanımlanmıştır. Bu gerçek bir kapsülleme (encapsulation) örneğidir—uygulama detayları modülünüzün kullanıcılarından tamamen gizlenir.

Kopya kağıdı

Opaque pointer deseni, bir türün bildirimini tanımından ayırarak uygulama detaylarını gizler.

Başlık dosyası yalnızca bir ön bildirim (forward declaration) içerir:

// counter.h
#ifndef COUNTER_H
#define COUNTER_H

typedef struct Counter Counter;  // Tamamlanmamış tür

Counter *create_counter(int start);
void free_counter(Counter *c);

#endif

Kaynak dosya gerçek struct tanımını içerir:

// counter.c
#include "counter.h"
#include <stdlib.h>

struct Counter {
    int value;      // Dışarıdan gizli
    int step;
};

Counter *create_counter(int start) {
    Counter *c = malloc(sizeof(Counter));
    c->value = start;
    c->step = 1;
    return c;
}

void free_counter(Counter *c) {
    free(c);
}

Struct tanımı yalnızca .c dosyasında görünür. Başlık dosyasını dahil eden dosyalar türün var olduğunu bilir ancak üyelerine doğrudan erişemez. Bu, C'de gerçek kapsülleme (encapsulation) sağlar.

Kendin dene

#include <stdio.h>
#include "timer.h"

int main() {
    int seconds;
    scanf("%d", &seconds);
    
    // TODO: Sağlanan saniye değeri ile bir zamanlayıcı oluştur
    
    // TODO: "Timer created" yazdır
    
    // TODO: Zamanlayıcıyı serbest bırak
    
    // TODO: "Timer freed" yazdır
    
    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.

Object Oriented Programming bölümündeki tüm dersler