चलिए पूरे इंजीनियरिंग समाधान के बारे में बात करते हैं जिसे पुराने दिनों में सर्वोत्तम अभ्यास माना जाता था।
structs के साथ समस्या यह है कि सब कुछ सार्वजनिक है इसलिए कोई डेटा छुपा नहीं है।
हम इसे ठीक कर सकते हैं।
आप दो शीर्षलेख फ़ाइलें बनाते हैं। एक "सार्वजनिक" हेडर फ़ाइल है जो आपके कोड के क्लाइंट द्वारा उपयोग की जाती है। यह इस तरह परिभाषाओं में शामिल हैं:
typedef void (*fDisposeFunction)(void *memoryBlock);
typedef struct {
fDisposeFunction _dispose;
} t_DisposableStruct;
typedef struct {
t_DisposableStruct_disposer; /* must be first */
PID _pid;
/* etc */
} t_ProcessStruct;
typedef struct {
t_DisposableStruct_disposer; /* must be first */
PERM_FLAGS _flags;
/* etc */
} t_PermissionsStruct;
और फिर अपने कार्यान्वयन में आप कुछ इस तरह कर सकते हैं::
static void DisposeMallocBlock(void *process) { if (process) free(process); }
static void *NewMallocedDisposer(size_t size)
{
assert(size > sizeof(t_DisposableStruct);
t_DisposableStruct *disp = (t_DisposableStruct *)malloc(size);
if (disp) {
disp->_dispose = DisposeMallocBlock;
}
return disp;
}
static void DisposeUsingDisposer(t_DisposableStruct *ds)
{
assert(ds);
ds->_dispose(ds);
}
t_ProcessHandle NewProcess()
{
t_ProcessHandle proc = (t_ProcessHandle)NewMallocedDisposer(sizeof(t_ProcessStruct));
if (proc) {
proc->PID = NextPID(); /* etc */
}
return proc;
}
void DisposeProcess(t_ProcessHandle proc)
{
DisposeUsingDisposer(&(proc->_disposer));
}
typedef struct t_ProcessStruct *t_ProcessHandle;
extern t_ProcessHandle NewProcess();
extern void DisposeProcess(t_ProcessHandle handle);
typedef struct t_PermissionsStruct *t_PermissionsHandle;
extern t_PermissionsHandle NewPermissions();
extern void DisposePermissions(t_PermissionsHandle handle);
extern void SetProcessPermissions(t_ProcessHandle proc, t_PermissionsHandle perm);
तो आप है कि इस तरह निर्धारणों वाली एक निजी हेडर फाइल बनाने
क्या होता है कि आप अपने सार्वजनिक हेडर फ़ाइलों में अपने structs के लिए घोषणाएं करते हैं। अब आपके structs अपारदर्शी हैं, जिसका मतलब है कि ग्राहक उनके साथ डिक नहीं कर सकते हैं। फिर, पूर्ण घोषणा में, आप प्रत्येक संरचना की शुरुआत में एक विनाशक शामिल करते हैं जिसे आप सामान्य रूप से कॉल कर सकते हैं। आप उसी मॉलोक आवंटक का उपयोग उसी व्यक्ति के लिए एक ही निपटान समारोह के लिए कर सकते हैं। आप उन तत्वों के लिए सार्वजनिक सेट/कार्य प्राप्त करते हैं जिन्हें आप उजागर करना चाहते हैं।
अचानक, आपका कोड बहुत अधिक सचेत है। आप केवल आवंटकों या फ़ंक्शन से structs प्राप्त कर सकते हैं जो आवंटकों को कॉल करते हैं, जिसका अर्थ है कि आप प्रारंभिकता को बाधित कर सकते हैं। आप विनाशकों में निर्माण करते हैं ताकि वस्तु को नष्ट किया जा सके। और तुम जाओ वैसे, t_DisposableStruct से बेहतर नाम t_vTableStruct हो सकता है, क्योंकि यह वही है। अब आप वर्चुअल विरासत बना सकते हैं जिसमें vTableStruct है जो सभी फ़ंक्शन पॉइंटर्स हैं। आप उन चीजों को भी कर सकते हैं जिन्हें आप शुद्ध ओओ भाषा (आमतौर पर) में नहीं कर सकते हैं, जैसे फ्लाई पर vtable के चुनिंदा तत्वों को बदलना।
महत्वपूर्ण बात यह है कि structs को सुरक्षित और प्रारंभिक बनाने के लिए एक इंजीनियरिंग पैटर्न है।
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define new(TYPE, ...) memdup(&(TYPE){ __VA_ARGS__ }, sizeof(TYPE))
void * memdup(const void * obj, size_t size)
{
void * copy = malloc(size);
return copy ? memcpy(copy, obj, size) : NULL;
}
struct point
{
int x;
int y;
};
int main()
{
int * i = new(int, 1);
struct point * p = new(struct point, 2, 3);
printf("%i %i %i", *i, p->x, p->y);
return 0;
}
ओह सीफ्रंट, हम आपको कैसे याद करते हैं। – joeforker
... एक भयानक जलती हुई धड़कन की तरह। – Randolpho
और सीफ्रंट ने शुरुआत में कन्स्ट्रक्टर को कैसे संभाला है? – claf