C derleme zamanı kapsülleme nedir?


9

C'nin C ++ 'a göre avantajlarını araştırırken, bu paragrafa rastladım:

C'de kapsülleme yapmanın standart yolu, bir yapıyı iletmek ve sadece işlevler aracılığıyla verilerine erişime izin vermektir. Bu yöntem ayrıca derleme zamanı kapsüllemesi oluşturur. Derleme zamanı kapsülleme, veri yapısı üyelerini, istemci kodunu (arayüzümüzü kullanan diğer kod) yeniden derlemeden değiştirmemize olanak tanır. Öte yandan C ++ kapsülleme yapmanın standart yolu (sınıfları kullanarak), özel üye değişkenleri eklerken veya kaldırırken istemci kodunun yeniden derlenmesini gerektirir.

Bir yapıyı bildirmenin ve üyelere işlevler aracılığıyla erişmenin yapının uygulama ayrıntılarını nasıl gizlediğini anlıyorum. Ne anlamıyorum özellikle bu çizgi:

Derleme zamanı kapsüllemesi, veri yapısı üyelerini , istemci kodunu (arayüzümüzü kullanan diğer kod) derlemeden değiştirmemize olanak tanır .

Bu hangi senaryoda uygulanabilir?


Temel olarak, iç structkısmı bilinmeyen bir kara kutudur. İstemci dahili bilgileri bilmiyorsa, bunlara asla doğrudan erişemez ve bunları istediğiniz zaman değiştirebilirsiniz. Bu, OOP'deki kapsüllemeye benzer. İç kısımlar özeldir ve nesneyi yalnızca genel yöntemleri kullanarak değiştirirsiniz.
Sulthan

Bu her zaman doğru değildir. Bir yapının üyelerini eklemeye / kaldırmaya karar verirseniz, boyutunu değiştirirsiniz. Bu, istemci kodunun yeniden derlenmesini gerektirecektir.
DarkAtom

2
@DarkAtom Doğru değil! İstemci içeriği ( opak bir yapı) bilmiyorsa, boyutunu bilmiyor, bu nedenle boyutu değiştirmek sorun değil.
Adrian Mole

1
@DarkAtom: Bir yapıya yalnızca işlevler yoluyla erişime izin verilmesi, yalnızca işlevler aracılığıyla tahsis edilmesini içerir. Kütüphane bir yapı tahsis etme işlevi sağlayacak ve istemci asla boyutunu bilemeyecektir. Boyutun değiştirilmesi istemcinin yeniden derlenmesini gerektirmez.
Eric Postpischil

3
Bu teknik olarak aynı fikri C ++ 'da uygulayabileceğiniz (ve genellikle uygulayabileceğiniz) teknik olarak bir "C ++ C ++ avantajı" değildir. Yukarı bak "Pimpl" deyim .
user4815162342

Yanıtlar:


4

Bunun gerçekleşebileceği olası gerçek dünya senaryosu, sabit disk alanının çok sınırlı olduğu günlerde yazılmış bir veritabanı kitaplığının bir tarihin 'yıl' alanını depolamak için tek bir bayt kullanmasıdır (örn. 11-NOV-1973) 73yıl için olurdu ). Ancak, 2000 Yılı geldiğinde, bu artık yeterli olmayacaktı ve yılın o zaman kısa (16 bit) bir tamsayı olarak saklanması gerekiyordu. Bu kütüphane için ilgili (çok basitleştirilmiş) başlık şu olabilir:

// dbEntry.h
typedef struct _dbEntry dbEntry;

dbEntry* CreateDBE(int day, int month, int year, int otherData);
void DeleteDBE(dbEntry* entry);
int GetYear(dbEntry* entry);

Ve bir 'müşteri' programı:

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

int main()
{
    int dataBlob = 42;
    dbEntry* test = CreateDBE(17, 11, 2019, dataBlob);
    //...
    int year = GetYear(test);
    printf("Year = %d\n", year);
    //...
    DeleteDBE(test);
    return 0;
}

'Orijinal' uygulama:

#include <stdlib.h>
#include "dbEntry.h"

struct _dbEntry {
    unsigned char d;
    unsigned char m;
    unsigned char y;    // Fails at Y2K!
    int dummyData;
};

dbEntry* CreateDBE(int day, int month, int year, int otherData)
{
    dbEntry* local = malloc(sizeof(dbEntry));
    local->d = (unsigned char)(day);
    local->m = (unsigned char)(month);
    local->y = (unsigned char)(year % 100);
    local->dummyData = otherData;
    return local;
}

void DeleteDBE(dbEntry* entry)
{
    free(entry);
}

int GetYear(dbEntry* entry)
{
    return (int)(entry->y);
}

Daha sonra, Y2K yaklaşımında, bu uygulama dosyası aşağıdaki gibi değiştirilecektir (diğer her şey el değmeden bırakılır):

struct _dbEntry {
    unsigned char d;
    unsigned char m;
    unsigned short y;   // Can now differentiate 1969 from 2069
    int dummyData;
};

dbEntry* CreateDBE(int day, int month, int year, int otherData)
{
    dbEntry* local = malloc(sizeof(dbEntry));
    local->d = (unsigned char)(day);
    local->m = (unsigned char)(month);
    local->y = (unsigned short)(year);
    local->dummyData = otherData;
    return local;
}

İstemcinin yeni (Y2K güvenli) sürümü kullanacak şekilde güncellenmesi gerektiğinde, kod değişikliği gerekmez. Aslında, olabilir hatta yeniden derleme gerekmez: sadece bağlama yeniden (o kadar buysa) güncellendi nesne kitaplığına olabilir yeterli.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.