C में संकलन-समय एनकैप्सुलेशन क्या है?


9

जब मैं C ++ से अधिक C के फायदों पर शोध कर रहा था, तो मैं इस पैराग्राफ में आया:

सी में मानक तरीका है एनकैप्सुलेशन करने के लिए एक संरचना की घोषणा करना और केवल फ़ंक्शन के माध्यम से अपने डेटा तक पहुंच की अनुमति देना है। इस विधि से संकलन समय का अंतराल भी बनता है। संकलन समय एनकैप्सुलेशन हमें क्लाइंट कोड (हमारे इंटरफ़ेस का उपयोग कर अन्य कोड) के पुनर्संयोजन के बिना डेटा संरचनाओं के सदस्यों को बदलने की अनुमति देता है। दूसरी ओर एन्कैप्सुलेशन C ++ करने का मानक तरीका (कक्षाओं का उपयोग करके) निजी कोड वेरिएबल्स को जोड़ते या हटाते समय क्लाइंट कोड के पुन: उपयोग की आवश्यकता होती है।

मैं समझता हूं कि कैसे एक संरचना की घोषणा करना और कार्यों के माध्यम से अपने सदस्यों तक पहुंचना संरचना के कार्यान्वयन के विवरण को छुपाता है। मुझे समझ में नहीं आता कि यह रेखा क्या है:

संकलन समय एनकैप्सुलेशन हमें क्लाइंट कोड (हमारे इंटरफ़ेस का उपयोग कर अन्य कोड) के पुनर्संयोजन के बिना डेटा संरचनाओं के सदस्यों को बदलने की अनुमति देता है ।

यह किस परिदृश्य में लागू है?


असल में, structअज्ञात इंटर्ल्स वाला एक ब्लैक बॉक्स है। यदि क्लाइंट को इंटर्नल का पता नहीं है, तो यह कभी भी सीधे उन तक नहीं पहुंच सकता है और आप उन्हें इच्छानुसार बदल सकते हैं। यह ओओपी में एनकैप्सुलेशन के समान है। इंटर्नल्स निजी हैं और आप केवल सार्वजनिक तरीकों का उपयोग करके वस्तु को बदलते हैं।
सुल्तान

यह हमेशा सही नहीं होता। यदि आप किसी संरचना के सदस्यों को जोड़ने / हटाने का निर्णय लेते हैं, तो आप इसका आकार बदलते हैं। इसके लिए क्लाइंट कोड को फिर से तैयार करना होगा।
डार्कअटोम

2
@DarkAtom सच नहीं है! यदि ग्राहक सामग्री (एक अपारदर्शी संरचना) को नहीं जानता है, तो यह उसके आकार को नहीं जानता है, इसलिए आकार को बदलना कोई समस्या नहीं है।
एड्रियन मोल

1
@DarkAtom: केवल संरचना के लिए कार्यों के माध्यम से पहुंच की अनुमति केवल कार्यों के माध्यम से आवंटन शामिल है। पुस्तकालय एक संरचना आवंटित करने के लिए एक समारोह प्रदान करेगा, और ग्राहक को कभी भी इसका आकार नहीं पता होगा। आकार बदलने से ग्राहक को पुन: जमा करने की आवश्यकता नहीं होती है।
एरिक पोस्टपिसिल

3
ध्यान दें कि यह तकनीकी रूप से "C + C C का लाभ" नहीं है जैसा कि आप कर सकते हैं (और अक्सर करते हैं) C ++ में एक ही विचार लागू करते हैं। ऊपर देखो "pimpl" मुहावरा
user4815162342

जवाबों:


4

एक वास्तविक वास्तविक परिदृश्य जहां ऐसा होता है जब डेटाबेस लाइब्रेरी, उन दिनों में लिखी जाती है जब हार्ड-डिस्क स्थान बहुत सीमित था, एक तारीख के 'वर्ष' क्षेत्र को संग्रहीत करने के लिए एक एकल बाइट का उपयोग करता था (जैसे 11-NOV-1973 73वर्ष के लिए होगा )। लेकिन, जब वर्ष 2000 आया, तो यह अब पर्याप्त नहीं होगा, और वर्ष को तब एक छोटे (16-बिट) पूर्णांक के रूप में संग्रहीत किया जाना था। इस लाइब्रेरी के लिए प्रासंगिक (बहुत सरलीकृत) हेडर यह हो सकता है:

// dbEntry.h
typedef struct _dbEntry dbEntry;

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

और एक 'ग्राहक' कार्यक्रम होगा:

#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;
}

'मूल' कार्यान्वयन:

#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);
}

फिर, Y2K के दृष्टिकोण पर, यह कार्यान्वयन फ़ाइल निम्नानुसार बदल जाएगी (बाकी सब कुछ अछूता रहा):

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;
}

जब क्लाइंट को नए (Y2K-safe) संस्करण का उपयोग करने के लिए अद्यतन करने की आवश्यकता होती है, तो कोई कोड परिवर्तन की आवश्यकता नहीं होगी। वास्तव में, आपको पुन: संकलित करने की भी आवश्यकता नहीं हो सकती है : बस अपडेट की गई ऑब्जेक्ट लाइब्रेरी को फिर से लिंक करना (यदि ऐसा है तो) पर्याप्त हो सकता है


2

नोट: निम्नलिखित सूची गैर-संपूर्ण होगी। संपादन का स्वागत है!

लागू परिदृश्यों में शामिल हैं:

  • मल्टी-मॉड्यूल अनुप्रयोग जहां आप किसी कारण से पुनर्मूल्यांकन नहीं चाहते हैं।
  • पुस्तकालयों में उपयोग की जाने वाली संरचनाएँ, जहाँ आप लाइब्रेरी के उपयोगकर्ताओं को हर बार जब आप एक (प्रकाशित) संरचना को बदलते हैं, तो उसे दोबारा इस्तेमाल करने के लिए बाध्य नहीं करना चाहते हैं।
  • संरचनाएं जो अलग-अलग प्लेटफार्मों पर अलग-अलग तत्व रखती हैं, मॉड्यूल काम करता है।

इस तरह की सबसे ज्ञात संरचना है FILE। आप fopen()सफल होने पर केवल कॉल करते हैं और पॉइंटर प्राप्त करते हैं। यह पॉइंटर तब एक दूसरे फ़ंक्शन को सौंप दिया जाता है जो फाइलों पर काम करता है। लेकिन आप नहीं जानते हैं - और आप जानना नहीं चाहते हैं - विवरण, जैसे निहित तत्व और आकार।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.