कोई व्यक्ति C में ऑब्जेक्ट-ओरिएंटेड कोड कैसे लिखेगा? [बन्द है]


499

C में ऑब्जेक्ट-ओरिएंटेड कोड लिखने के कुछ तरीके क्या हैं? खासकर बहुरूपता के संबंध में।


C में यह स्टैक ओवरफ्लो प्रश्न ऑब्जेक्ट-ओरिएंटेशन भी देखें ।


1
<a href=" ldeniau.web.cern.ch/ldeniau/html/oopc.html"> लॉरेंट डेनियायू द्वारा ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग C में </a>


25
@Camilo मार्टिन: मैं जानबूझकर पूछा कर सकते हैं नहीं करना चाहिए । मैं वास्तव में सी में ओओपी का उपयोग करने में दिलचस्पी नहीं रखता हूं। हालांकि, सी में ओओ के समाधानों को देखकर, मैं / हम सी की सीमाओं और / या लचीलेपन के बारे में अधिक जानने के लिए खड़े हैं और बहुरूपता को लागू करने और उपयोग करने के रचनात्मक तरीकों के बारे में भी।
दीनाह

5
OO सिर्फ एक पैटर्न है। यहां देखें, यह .bat फ़ाइलें में भी किया जा सकता है : dirk.rave.org/chap9.txt (यदि आप पर्याप्त रुचि रखते हैं, तो कोई भी पैटर्न किसी भी प्रोग्रामिंग भाषा पर लागू किया जा सकता है, मुझे लगता है)। यह विचार के लिए अच्छा भोजन है, हालांकि। और शायद बहुत कुछ सीखा जा सकता है ऐसे पैटर्न लागू करने से जो हम उन भाषाओं पर देते हैं जो उनके पास नहीं हैं।
कैमिलो मार्टिन

6
जीटीके - 'स्क्यू मी, गोबजेक्ट - वास्तव में सी। में ओओपी (सॉर्टा) का एक बहुत अच्छा उदाहरण है। इसलिए सी इंटरपोलीबिलिटी के लिए @Camilo को जवाब देना है।
new123456

जवाबों:


361

हाँ। वास्तव में एक्सल श्राइनर अपनी पुस्तक "ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग इन एएनएसआई-सी" मुफ्त में प्रदान करता है जो विषय को काफी अच्छी तरह से कवर करता है।


28
जबकि इस पुस्तक की अवधारणाएँ ठोस हैं, आप प्रकार की सुरक्षा खो देंगे।
दीपिर

22
इससे पहले कि हम डिजाइन पैटर्न के रूप में जानते हैं, क्या डिजाइन पैटर्न "ऑब्जेक्ट ओरिएंटेशन" के रूप में जाना जाता था; कचरा संग्रहण के साथ भी ऐसा ही है। वे अब बहुत प्रभावित हैं, हम भूल जाते हैं, जब वे पहली बार तैयार हो रहे थे, यह उसी तरह से था जैसा हम आज के पैटर्न पैटर्न के बारे में सोचते हैं
Dexygen

11
आप इसे सीधे लेखक की साइट से प्राप्त कर सकते हैं: cs.rit.edu/~ats/books/ooc.pdf उसी लेखक के अन्य कागजात: cs.rit.edu/~ats/books/index.html
pakman

10
इस संग्रह से उचित संग्रह (पुस्तक + स्रोत-कोड उदाहरण) उपलब्ध है। ANSI-C
डेविड सी। रैंकिन

3
क्या इस पुस्तक की समीक्षा की गई है? पहले पृष्ठ के पहले पैराग्राफ के पहले वाक्य में एक टाइपो है।
Dagrooms

343

चूंकि आप बहुरूपता के बारे में बात कर रहे हैं तो हाँ, आप कर सकते हैं, हम उस तरह के सामान कर रहे थे जैसे सी ++ के बारे में आया था।

मूल रूप से आप structउस डेटा के लिए संबंधित फ़ंक्शन को इंगित करने के लिए डेटा और फ़ंक्शन पॉइंटर्स की एक सूची दोनों का उपयोग करते हैं।

इसलिए, संचार वर्ग में, आपके पास एक खुला, पढ़ना, लिखना और पास कॉल होगा जो संरचना में चार फ़ंक्शन बिंदुओं के रूप में बनाए रखा जाएगा, एक वस्तु के लिए डेटा के साथ, कुछ इस तरह से:

typedef struct {
    int (*open)(void *self, char *fspec);
    int (*close)(void *self);
    int (*read)(void *self, void *buff, size_t max_sz, size_t *p_act_sz);
    int (*write)(void *self, void *buff, size_t max_sz, size_t *p_act_sz);
    // And data goes here.
} tCommClass;

tCommClass commRs232;
commRs232.open = &rs232Open;
: :
commRs232.write = &rs232Write;

tCommClass commTcp;
commTcp.open = &tcpOpen;
: :
commTcp.write = &tcpWrite;

बेशक, ऊपर दिए गए कोड सेगमेंट वास्तव में "कंस्ट्रक्टर" जैसे होंगे rs232Init()

जब आप उस वर्ग से 'विरासत' लेते हैं, तो आप केवल अपने कार्यों को इंगित करने के लिए संकेत बदलते हैं। हर कोई जो उन कार्यों को बुलाता है, वह फ़ंक्शन पॉइंटर के माध्यम से करता है, जो आपको आपकी बहुरूपता देता है:

int stat = (commTcp.open)(commTcp, "bigiron.box.com:5000");

एक मैनुअल vtable की तरह।

यहां तक ​​कि वर्चुअल क्लास भी हो सकती है, जहां पर NULL -the बिहेवियर के पॉइंट सेट करके वर्चुअल क्लास C ++ से थोड़ी अलग होगी (कंपाइल टाइम में एरर के बजाय रन-टाइम पर कोर डंप)।

यहाँ नमूना कोड का एक टुकड़ा है जो इसे प्रदर्शित करता है। प्रथम शीर्ष-स्तरीय वर्ग संरचना:

#include <stdio.h>

// The top-level class.

typedef struct sCommClass {
    int (*open)(struct sCommClass *self, char *fspec);
} tCommClass;

फिर हमारे पास TCP 'उपवर्ग' के लिए कार्य हैं:

// Function for the TCP 'class'.

static int tcpOpen (tCommClass *tcp, char *fspec) {
    printf ("Opening TCP: %s\n", fspec);
    return 0;
}
static int tcpInit (tCommClass *tcp) {
    tcp->open = &tcpOpen;
    return 0;
}

और HTTP एक:

// Function for the HTTP 'class'.

static int httpOpen (tCommClass *http, char *fspec) {
    printf ("Opening HTTP: %s\n", fspec);
    return 0;
}
static int httpInit (tCommClass *http) {
    http->open = &httpOpen;
    return 0;
}

और अंत में इसे कार्रवाई में दिखाने के लिए एक परीक्षण कार्यक्रम:

// Test program.

int main (void) {
    int status;
    tCommClass commTcp, commHttp;

    // Same 'base' class but initialised to different sub-classes.

    tcpInit (&commTcp);
    httpInit (&commHttp);

    // Called in exactly the same manner.

    status = (commTcp.open)(&commTcp, "bigiron.box.com:5000");
    status = (commHttp.open)(&commHttp, "http://www.microsoft.com");

    return 0;
}

यह उत्पादन का उत्पादन करता है:

Opening TCP: bigiron.box.com:5000
Opening HTTP: http://www.microsoft.com

इसलिए आप देख सकते हैं कि उप-वर्ग के आधार पर विभिन्न कार्यों को बुलाया जा रहा है।


52
एनकैप्सुलेशन बहुत आसान है, बहुरूपता उल्लेखनीय है - लेकिन विरासत मुश्किल है
मार्टिन बेकेट

5
lwn.net ने हाल ही में उपर्युक्त उत्तर के समान ही स्टिक के विषय पर ऑब्जेक्ट ओरिएंटेड डिज़ाइन पैटर्न शीर्षक से एक लेख प्रकाशित किया है - वह है, एक संरचना युक्त फ़ंक्शन पॉइंटर्स, या किसी ऐसे पॉइंटर को इंगित करता है जिसमें ऐसे कार्य होते हैं जो एक पॉइंटर को ले जाते हैं एक पैरामीटर के रूप में हम जिस डेटा के साथ काम कर रहे हैं, उसके साथ संरचना।
मूलांक

11
+1 अच्छा उदाहरण! यद्यपि यदि कोई वास्तव में इस सड़क से नीचे जाना चाहता है, तो यह "उदाहरण" संरचनाओं के लिए एक एकल फ़ील्ड को उनके "वर्चुअल टेबल" उदाहरण की ओर इंगित करने के लिए अधिक उपयुक्त होगा , जिसमें एक ही स्थान पर उस प्रकार के सभी वर्चुअल फ़ंक्शन शामिल हैं। यानी आपका tCommClassनाम बदल दिया जाएगा tCommVT, और एक tCommClassसंरचना में केवल tCommVT vt"एक और केवल" वर्चुअल-टेबल की ओर इशारा करते हुए डेटा फ़ील्ड और एक एकल फ़ील्ड होगा। प्रत्येक उदाहरण के साथ सभी बिंदुओं को ले जाने से अनावश्यक ओवरहेड जुड़ जाता है और आप C ++, IMHO की तुलना में जावास्क्रिप्ट में सामान कैसे करेंगे, इससे अधिक मिलता जुलता है।
ग्रू

1
तो यह एकल इंटरफ़ेस के कार्यान्वयन को दर्शाता है, लेकिन कई इंटरफेस को लागू करने के बारे में क्या? या कई विरासत?
वेबर 2

वेबर, यदि आप C ++ की सभी कार्यक्षमता चाहते हैं, तो आपको संभवतः C ++ का उपयोग करना चाहिए। यह सवाल विशेष रूप से बहुरूपता, वस्तुओं की एक अलग "रूप" लेने की क्षमता के बारे में पूछा गया। आप निश्चित रूप से सी में इंटरफेस और मल्टीपल इनहेरिटेंस कर सकते हैं, लेकिन यह अतिरिक्त काम का एक उचित हिस्सा है, और आपको सी ++ बिल्ट-इन सामान का उपयोग करने के बजाय स्मार्ट को स्वयं का प्रबंधन करना होगा।
पैक्सडीब्लो

86

नाम स्थान अक्सर कर के होते हैं:

stack_push(thing *)

के बजाय

stack::push(thing *)

C ++ वर्ग जैसी किसी चीज़ में C संरचना बनाने के लिए आप इसे चालू कर सकते हैं:

class stack {
     public:
        stack();
        void push(thing *);
        thing * pop();
        static int this_is_here_as_an_example_only;
     private:
        ...
};

में

struct stack {
     struct stack_type * my_type;
     // Put the stuff that you put after private: here
};
struct stack_type {
     void (* construct)(struct stack * this); // This takes uninitialized memory
     struct stack * (* operator_new)(); // This allocates a new struct, passes it to construct, and then returns it
     void (*push)(struct stack * this, thing * t); // Pushing t onto this stack
     thing * (*pop)(struct stack * this); // Pops the top thing off the stack and returns it
     int this_is_here_as_an_example_only;
}Stack = {
    .construct = stack_construct,
    .operator_new = stack_operator_new,
    .push = stack_push,
    .pop = stack_pop
};
// All of these functions are assumed to be defined somewhere else

और करो:

struct stack * st = Stack.operator_new(); // Make a new stack
if (!st) {
   // Do something about it
} else {
   // You can use the stack
   stack_push(st, thing0); // This is a non-virtual call
   Stack.push(st, thing1); // This is like casting *st to a Stack (which it already is) and doing the push
   st->my_type.push(st, thing2); // This is a virtual call
}

मैंने विध्वंसक या नष्ट नहीं किया, लेकिन यह उसी पैटर्न का अनुसरण करता है।

this_is_here_as_an_example_only एक स्थिर वर्ग चर की तरह है - एक प्रकार के सभी उदाहरणों के बीच साझा किया जाता है। सभी विधियाँ वास्तव में स्थिर हैं, सिवाय इसके कि कुछ इसे ले *


1
@nategoose - st->my_type->push(st, thing2);के बजायst->my_type.push(st, thing2);
फ़ेब्रिकियो

@nategoose: या struct stack_type my_type; इसके बजायstruct stack_type * my_type;
फैब्रिकियो

3
मुझे कक्षा के लिए एक संरचना होने की अवधारणा पसंद है। लेकिन एक सामान्य Classसंरचना के बारे में कैसे ? यह O ++ C को C ++ से अधिक गतिशील बनाता है । उस के बारे में कैसा है? वैसे, +1।
लिनक्स जूल 28'12

54

मेरा मानना ​​है कि अपने आप में उपयोगी होने के अलावा, OOP को C में लागू करना OOP सीखने और इसके आंतरिक कामकाज को समझने का एक शानदार तरीका है । कई प्रोग्रामर्स के अनुभव से पता चला है कि कुशलतापूर्वक और आत्मविश्वास से एक तकनीक का उपयोग करने के लिए, एक प्रोग्रामर को समझना चाहिए कि अंतर्निहित अवधारणाओं को अंततः कैसे लागू किया जाता है। सी में कक्षाएं, वंशानुक्रम और बहुरूपता का अनुकरण करना बस यही सिखाता है।

मूल प्रश्न का उत्तर देने के लिए, यहाँ कुछ संसाधन दिए गए हैं जो सिखाते हैं कि C में OOP कैसे करें:

एंबेडेडगुरुस.कॉम ब्लॉग पोस्ट "ऑब्जेक्ट आधारित प्रोग्रामिंग इन सी" से पता चलता है कि पोर्टेबल सी में कक्षाएं और एकल विरासत को कैसे लागू किया जाए: http://embeddedgurus.com/state-space/2008/01/object-based-programming-in-c /

अनुप्रयोग नोट "" सी + "- ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग इन सी" प्रीप्रोसेसर मैक्रोज़ का उपयोग करके सी में कक्षाएं, एकल वंशानुक्रम और देर से बाध्यकारी (बहुरूपता) को लागू करने का तरीका दिखाता है: http://www.state-machine.com/resources-cplus_3। 0_manual.pdf , उदाहरण कोड http://www.state-machine.com/resources/cplus_3b.ip से उपलब्ध है


4
C + मैनुअल के लिए नया url: state-machine.com/doc/cplus_3.0_manual.pdf
लियांग

32

मैंने इसे पूरा होते देखा है। मैं इसकी सिफारिश नहीं करूंगा। सी ++ मूल रूप से इस तरह से एक प्रीप्रोसेसर के रूप में शुरू हुआ जिसने सी कोड को मध्यवर्ती चरण के रूप में उत्पादित किया।

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


5
"आखिरकार, आप C ++ को फिर से लिखना चाहते हैं" मुझे आश्चर्य है कि क्या / अगर ऐसा होगा तो डर था।
दीना

39
या, आप उद्देश्य सी को फिर से लिख सकते हैं, जो एक बहुत अधिक आकर्षक परिणाम होगा।
प्रो। फाल्कन कॉन्ट्रैक्ट ने

3
OOP का वर्ग-कम स्वाद है, जैसे कि जावास्क्रिप्ट में , जहां गुरु कहते हैं: "हमें बहुत सी समान वस्तुओं को बनाने के लिए कक्षाओं की आवश्यकता नहीं है।" लेकिन मुझे डर है कि सी। नॉट (अभी तक) को हासिल करने की स्थिति में यह आसान नहीं है, हालांकि। (क्या कोई क्लोन बनाने के लिए एक क्लोन () दिनचर्या है?)
लुमी

1
एक और स्मार्ट लोग, जिन्हें वास्तव में इसे लागू करना था और उस कार्यान्वयन को तेज करना था (Google, V8 इंजन) ने जावास्क्रिप्ट बैक में सब कुछ (छिपा हुआ) वर्ग जोड़ दिया है।
क्यूबसप्लि 42

glibC में ऑब्जेक्टिव तरीके से नहीं लिखा है?
क्रविमीर

26

यकीन है कि संभव है। यह GObject है , जो फ्रेमवर्क सभी GTK + और GNOME पर आधारित है, करता है।


इस तरह के दृष्टिकोण के पेशेवरों / विपक्ष क्या हैं? अर्थात। C ++ का उपयोग करके इसे लिखना बहुत आसान है।
क्रविमीर

@kravemir खैर, C ++, C के समान पोर्टेबल नहीं है, और C ++ को कोड से लिंक करना थोड़ा कठिन है जो कि एक अलग C ++ कंपाइलर द्वारा संकलित किया जा सकता है। लेकिन हां, C ++ में कक्षाएं लिखना आसान है, हालांकि GObject वास्तव में इतना मुश्किल नहीं है (यह मानते हुए कि आप थोड़ा बॉयलर प्लेट को ध्यान में नहीं रखते हैं)।
एडविन बक

17

C stdio FILE उप-पुस्तकालय एक अप्रत्यक्ष सी में अमूर्तता, एनकैप्सुलेशन और मॉड्यूलरिटी बनाने का एक उत्कृष्ट उदाहरण है।

विरासत और बहुरूपता - अक्सर OOP के लिए आवश्यक माना अन्य पहलुओं - जरूरी उत्पादकता लाभ वे वादा प्रदान नहीं करते हैं और उचित तर्क है किया गया वे वास्तव में बाधा विकास और समस्या डोमेन के बारे में सोच सकते हैं कि।


क्या कर्डी परत पर सारगर्भित सार नहीं है? अगर मैं गलत नहीं हूं, तो सी-लाइब्रेरी उन्हें चरित्र फ़ाइलों / उपकरणों के रूप में मानती है, और कर्नेल ड्राइवर काम करते हैं, ...
kravemir

15

एक पशु और कुत्ते के साथ तुच्छ उदाहरण: आप दर्पण C ++ के व्यवहार्य तंत्र (मोटे तौर पर वैसे भी)। आप आवंटन और इंस्टेंटेशन (Animal_Alloc, Animal_New) को भी अलग करते हैं, इसलिए हम कई बार मॉलॉक () को कॉल नहीं करते हैं। हमें thisपॉइंटर को भी स्पष्ट रूप से पास करना होगा ।

यदि आप गैर-आभासी कार्य करने के लिए थे, तो यह सही है। आप उन्हें केवल व्यवहार्य और स्थिर कार्यों में शामिल नहीं करते हैं, एक thisपॉइंटर की आवश्यकता नहीं होती है । बहु विरासत में आम तौर पर अस्पष्टताओं को हल करने के लिए कई vtables की आवश्यकता होती है।

साथ ही, आपको अपवाद हैंडलिंग करने के लिए setjmp / longjmp का उपयोग करने में सक्षम होना चाहिए।

struct Animal_Vtable{
    typedef void (*Walk_Fun)(struct Animal *a_This);
    typedef struct Animal * (*Dtor_Fun)(struct Animal *a_This);

    Walk_Fun Walk;
    Dtor_Fun Dtor;
};

struct Animal{
    Animal_Vtable vtable;

    char *Name;
};

struct Dog{
    Animal_Vtable vtable;

    char *Name; // Mirror member variables for easy access
    char *Type;
};

void Animal_Walk(struct Animal *a_This){
    printf("Animal (%s) walking\n", a_This->Name);
}

struct Animal* Animal_Dtor(struct Animal *a_This){
    printf("animal::dtor\n");
    return a_This;
}

Animal *Animal_Alloc(){
    return (Animal*)malloc(sizeof(Animal));
}

Animal *Animal_New(Animal *a_Animal){
    a_Animal->vtable.Walk = Animal_Walk;
    a_Animal->vtable.Dtor = Animal_Dtor;
    a_Animal->Name = "Anonymous";
    return a_Animal;
}

void Animal_Free(Animal *a_This){
    a_This->vtable.Dtor(a_This);

    free(a_This);
}

void Dog_Walk(struct Dog *a_This){
    printf("Dog walking %s (%s)\n", a_This->Type, a_This->Name);
}

Dog* Dog_Dtor(struct Dog *a_This){
    // Explicit call to parent destructor
    Animal_Dtor((Animal*)a_This);

    printf("dog::dtor\n");

    return a_This;
}

Dog *Dog_Alloc(){
    return (Dog*)malloc(sizeof(Dog));
}

Dog *Dog_New(Dog *a_Dog){
    // Explict call to parent constructor
    Animal_New((Animal*)a_Dog);

    a_Dog->Type = "Dog type";
    a_Dog->vtable.Walk = (Animal_Vtable::Walk_Fun) Dog_Walk;
    a_Dog->vtable.Dtor = (Animal_Vtable::Dtor_Fun) Dog_Dtor;

    return a_Dog;
}

int main(int argc, char **argv){
    /*
      Base class:

        Animal *a_Animal = Animal_New(Animal_Alloc());
    */
    Animal *a_Animal = (Animal*)Dog_New(Dog_Alloc());

    a_Animal->vtable.Walk(a_Animal);

    Animal_Free(a_Animal);
}

पुनश्च। यह C ++ कंपाइलर पर जांचा जाता है, लेकिन इसे C कंपाइलर पर काम करना आसान होना चाहिए।


typedefstructसी। में अंदर संभव नहीं है
मस्तूल

13

की जाँच करें GObject । यह C में OO और एक कार्यान्वयन है जो आप देख रहे हैं। यदि आप वास्तव में OO चाहते हैं, तो C ++ या किसी अन्य OOP भाषा के साथ जाएं। यदि आप OO भाषाओं से निपटने के लिए उपयोग किए जाते हैं, तो GObject कई बार काम करना कठिन हो सकता है, लेकिन किसी भी चीज़ की तरह, आपको सम्मेलनों और प्रवाह की आदत होगी।


12

यह पढ़ना दिलचस्प रहा है। मैं खुद उसी सवाल को टटोल रहा हूं, और इसके बारे में सोचने के फायदे इस प्रकार हैं:

  • एक गैर-ओओपी भाषा में ओओपी अवधारणाओं को कैसे लागू किया जाए, यह कल्पना करने की कोशिश मुझे ओओपी भाषा की ताकत (मेरे मामले में, सी ++) को समझने में मदद करती है। यह मुझे एक बेहतर प्रकार के आवेदन के लिए C या C ++ का उपयोग करने के बारे में बेहतर निर्णय लेने में मदद करता है - जहां एक का लाभ दूसरे को नापता है।

  • इस पर जानकारी और राय के लिए वेब ब्राउजिंग में मुझे एक लेखक मिला जो एक एम्बेडेड प्रोसेसर के लिए कोड लिख रहा था और केवल एक सी कंपाइलर उपलब्ध था: http://www.eetimes.com/discussion/other/4024626/Object-Oriented -सी-बनाना-फाउंडेशन-कक्षा-भाग -1

उनके मामले में, सादे C में OOP अवधारणाओं का विश्लेषण और अनुकूलन एक वैध खोज थी। ऐसा प्रतीत होता है कि वह ओवरहेड हिट के कारण कुछ ओओपी अवधारणाओं का त्याग करने के लिए खुला था, जिसके परिणामस्वरूप सी में उन्हें लागू करने का प्रयास किया गया था।

मैंने जो सबक लिया है, हाँ यह कुछ हद तक किया जा सकता है, और हाँ, इसे आज़माने के कुछ अच्छे कारण हैं।

अंत में, मशीन स्टैक पॉइंटर बिट्स को घुमा रही है, जिससे प्रोग्राम काउंटर जंप के आसपास हो जाता है और मेमोरी एक्सेस ऑपरेशन की गणना करता है। दक्षता के दृष्टिकोण से, आपके कार्यक्रम द्वारा किए गए इन गणनाओं में से कम, बेहतर ... लेकिन कभी-कभी हमें इस कर का भुगतान करना पड़ता है इसलिए हम अपने कार्यक्रम को इस तरह से व्यवस्थित कर सकते हैं जो मानव त्रुटि के लिए कम से कम अतिसंवेदनशील बनाता है। ओओपी भाषा संकलक दोनों पहलुओं को अनुकूलित करने का प्रयास करता है। प्रोग्रामर को C जैसी भाषा में इन अवधारणाओं को लागू करने में अधिक सावधानी बरतनी होगी।


10

आपको ऐप्पल के दस्तावेज़ीकरण को एपीआई के कोर फाउंडेशन सेट के लिए देखना उपयोगी हो सकता है। यह एक शुद्ध सी एपीआई है, लेकिन कई प्रकार ऑब्जेक्टिव-सी ऑब्जेक्ट समकक्षों के लिए तैयार हैं।

ऑब्जेक्टिव-सी के डिजाइन को देखने में भी आपको यह मददगार लग सकता है। यह C ++ से थोड़ा अलग है कि ऑब्जेक्ट सिस्टम को C फ़ंक्शन के संदर्भ में परिभाषित किया गया है, उदाहरण के objc_msg_sendलिए किसी ऑब्जेक्ट पर एक विधि को कॉल करना। कंपाइलर उन फ़ंक्शन कॉल में स्क्वायर ब्रैकेट सिंटैक्स का अनुवाद करता है, इसलिए आपको इसे जानने की ज़रूरत नहीं है, लेकिन आपके प्रश्न पर विचार करने से आपको यह सीखना उपयोगी हो सकता है कि यह हुड के नीचे कैसे काम करता है।


10

कई तकनीकें हैं जिनका उपयोग किया जा सकता है। सबसे महत्वपूर्ण एक और अधिक है कि परियोजना को कैसे विभाजित किया जाए। हम अपने प्रोजेक्ट में एक .h फ़ाइल और ऑब्जेक्ट के कार्यान्वयन के लिए एक .c फ़ाइल में घोषित किया जाता है। महत्वपूर्ण हिस्सा यह है कि सभी मॉड्यूल जिसमें .h फ़ाइल शामिल हैं, केवल एक ऑब्जेक्ट को एक के रूप में देखते हैं void *, और .c फ़ाइल एकमात्र ऐसा मॉड्यूल है जो संरचना के आंतरिक भाग को जानता है।

एक वर्ग के लिए कुछ इस तरह हम एक उदाहरण के रूप में FOO नाम:

.H फ़ाइल में

#ifndef FOO_H_
#define FOO_H_

...
 typedef struct FOO_type FOO_type;     /* That's all the rest of the program knows about FOO */

/* Declaration of accessors, functions */
FOO_type *FOO_new(void);
void FOO_free(FOO_type *this);
...
void FOO_dosomething(FOO_type *this, param ...):
char *FOO_getName(FOO_type *this, etc);
#endif

C कार्यान्वयन फ़ाइल कुछ इस तरह होगी।

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

struct FOO_type {
    whatever...
};


FOO_type *FOO_new(void)
{
    FOO_type *this = calloc(1, sizeof (FOO_type));

    ...
    FOO_dosomething(this, );
    return this;
}

इसलिए मैं उस मॉड्यूल के प्रत्येक फ़ंक्शन के लिए स्पष्ट रूप से एक ऑब्जेक्ट को पॉइंटर देता हूं। एक C ++ कंपाइलर इसे स्पष्ट रूप से करता है, और C में हम इसे स्पष्ट रूप से लिखते हैं।

मैं वास्तव thisमें अपने कार्यक्रमों में उपयोग करता हूं, यह सुनिश्चित करने के लिए कि मेरा कार्यक्रम C ++ में संकलित नहीं करता है, और मेरे सिंटैक्स हाइलाइटिंग संपादक में दूसरे रंग में होने का ठीक गुण है।

FOO_struct के क्षेत्रों को एक मॉड्यूल में संशोधित किया जा सकता है और किसी अन्य मॉड्यूल को अभी भी प्रयोग करने योग्य होने के लिए recompiled करने की आवश्यकता नहीं है।

उस शैली के साथ मैं पहले से ही OOP (डेटा एनकैप्सुलेशन) के फायदों का एक बड़ा हिस्सा संभालता हूं। फ़ंक्शन पॉइंटर्स का उपयोग करके, विरासत की तरह कुछ को लागू करना और भी आसान है, लेकिन ईमानदारी से, यह वास्तव में केवल शायद ही उपयोगी है।


6
यदि आप typedef struct FOO_type FOO_typeहेडर में शून्य टाइप करने के लिए करते हैं तो आपको टाइपिंग चेकिंग का अतिरिक्त लाभ मिलता है, जबकि अभी भी आपकी संरचना को उजागर नहीं किया गया है।
स्कॉट वेल्स

8

आप फ़ंक्शन पॉइंटर्स का उपयोग करके इसे नकली कर सकते हैं, और वास्तव में, मुझे लगता है कि सी ++ कार्यक्रमों को सी में संकलित करना सैद्धांतिक रूप से संभव है।

हालांकि, यह शायद ही कभी किसी भाषा को एक प्रतिमान का उपयोग करने के बजाय एक भाषा पर एक प्रतिमान को मजबूर करने के लिए समझ में आता है।


5
बहुत पहले C ++ कंपाइलर ने ठीक यही किया - इसने C ++ कोड को समतुल्य (लेकिन बदसूरत और गैर-मानव-पठनीय) C कोड में बदल दिया, जिसे तब C कंपाइलर द्वारा संकलित किया गया था।
एडम रोसेनफील्ड

2
EDG, Cfront और कुछ अन्य अभी भी ऐसा करने में सक्षम हैं। एक बहुत अच्छे कारण के साथ: हर प्लेटफ़ॉर्म में C ++ कंपाइलर नहीं होता है।
जैस्पर बेकर्स

किसी कारण से मुझे लगा कि सी-फ्रंट ने केवल कुछ सी ++ एक्सटेंशन (जैसे, संदर्भ) का समर्थन किया है, लेकिन पूर्ण ओओपी / डायनेमिक डिस्पैच एमुलेशन नहीं।
उड़ी

2
आप LLVM और C बैकएंड के साथ भी यही काम कर सकते हैं।
जिफरे

7

ऑब्जेक्ट ओरिएंटेड C, किया जा सकता है, मैंने उस प्रकार का कोड कोरिया में उत्पादन में देखा है, और यह सबसे भयानक राक्षस था जिसे मैंने वर्षों में देखा था (यह पिछले वर्ष (2007) जैसा था कि मैंने कोड देखा था)। तो हाँ यह किया जा सकता है, और हाँ लोगों ने इसे पहले भी किया है, और अभी भी इस दिन और उम्र में भी करते हैं। लेकिन मैं C ++ या ऑब्जेक्टिव-सी की सिफारिश करूंगा, दोनों अलग-अलग प्रतिमानों के साथ ऑब्जेक्ट ओरिएंटेशन प्रदान करने के उद्देश्य से C से जन्मी भाषाएँ हैं।


3
अगर लिनस आपकी टिप्पणी देखते हैं। वह निश्चित रूप से आपको हंसाएगा या शाप देगा
एंडर्स लिंड

7

यदि आप आश्वस्त हैं कि आप जिस समस्या को हल करने का प्रयास कर रहे हैं, उसके लिए एक OOP दृष्टिकोण बेहतर है, तो आप इसे गैर-OOP भाषा के साथ हल करने का प्रयास क्यों करेंगे? ऐसा लगता है कि आप नौकरी के लिए गलत उपकरण का उपयोग कर रहे हैं। C ++ या कुछ अन्य ऑब्जेक्ट ओरिएंटेड C वेरिएंट भाषा का उपयोग करें।

यदि आप पूछ रहे हैं क्योंकि आप सी में लिखी गई पहले से मौजूद बड़ी परियोजना पर कोड करना शुरू कर रहे हैं, तो आपको अपने स्वयं के (या किसी और के) ओओपी प्रतिमानों को परियोजना के बुनियादी ढांचे में मजबूर करने की कोशिश नहीं करनी चाहिए। परियोजना में पहले से मौजूद दिशानिर्देशों का पालन करें। सामान्य तौर पर, स्वच्छ एपीआई और पृथक पुस्तकालय और मॉड्यूल एक साफ ओओपी- ईश डिजाइन होने की दिशा में एक लंबा रास्ता तय करेंगे ।

यदि, इस सब के बाद, आप वास्तव में OOP C कर रहे हैं, तो इसे पढ़ें (PDF)।


36
वास्तव में इस सवाल का जवाब नहीं ...
ब्रायन पोस्टो

2
@ ब्रायन, पीडीएफ का लिंक सीधे सवाल का जवाब देने के लिए दिखाई देगा, हालांकि मेरे पास खुद की जांच करने का समय नहीं है।
मार्क रैनसम

5
पीडीएफ का लिंक इस विषय पर एक संपूर्ण पाठ्यपुस्तक प्रतीत होता है ... एक सुंदर प्रमाण, लेकिन यह मार्जिन में फिट नहीं होता है ...
ब्रायन पोस्टो

5
हां, सवाल का जवाब दें। यह पूछने के लिए पूरी तरह से वैध है कि किसी विशेष तरीके से भाषा का उपयोग कैसे किया जाए। अन्य भाषाओं पर राय के लिए कोई अनुरोध नहीं किया गया ...
टिम रिंग

9
@ ब्रायन और टिम रिंग: किसी विषय पर पुस्तक की सिफारिशों के लिए पूछा गया प्रश्न ; मैंने उसे एक पुस्तक का लिंक दिया जो विशेष रूप से इस विषय को संबोधित करती है। मैंने इस पर भी अपनी राय दी कि समस्या के लिए दृष्टिकोण इष्टतम क्यों नहीं हो सकता (जो मुझे लगता है कि यहाँ पर बहुत से लोग वोट और अन्य टिप्पणियों / उत्तरों के आधार पर सहमत होते हैं)। क्या मेरे उत्तर को बेहतर बनाने के लिए आपके पास कोई सुझाव है?
RarrRarrRarr

6

हाँ तुम कर सकते हो। लोग C ++ या Objective-C दृश्य में आने से पहले ऑब्जेक्ट ओरिएंटेड सी लिख रहे थे । C ++ और Objective-C दोनों, भागों में थे, C में प्रयुक्त कुछ OO अवधारणाओं को लेने का प्रयास करते हैं और उन्हें भाषा के भाग के रूप में औपचारिक रूप देते हैं।

यहाँ एक बहुत ही सरल प्रोग्राम है जो दिखाता है कि आप कैसे कुछ बना सकते हैं जो दिखता है-जैसा / एक तरीका है कॉल (ऐसा करने के बेहतर तरीके हैं। यह सिर्फ सबूत है कि भाषा अवधारणाओं का समर्थन करती है)।

#include<stdio.h>

struct foobarbaz{
    int one;
    int two;
    int three;
    int (*exampleMethod)(int, int);
};

int addTwoNumbers(int a, int b){
    return a+b;
}

int main()
{
    // Define the function pointer
    int (*pointerToFunction)(int, int) = addTwoNumbers;

    // Let's make sure we can call the pointer
    int test = (*pointerToFunction)(12,12);
    printf ("test: %u \n",  test);

    // Now, define an instance of our struct
    // and add some default values.
    struct foobarbaz fbb;
    fbb.one   = 1;
    fbb.two   = 2;
    fbb.three = 3;

    // Now add a "method"
    fbb.exampleMethod = addTwoNumbers;

    // Try calling the method
    int test2 = fbb.exampleMethod(13,36);
    printf ("test2: %u \n",  test2);

    printf("\nDone\n");
    return 0;
}

6

बेशक, यह बिल्ट-इन सपोर्ट वाली भाषा का उपयोग करने जैसा नहीं होगा। मैंने "ऑब्जेक्ट-ओरिएंटेड असेंबलर" भी लिखा है।


6

जोड़ने के लिए थोड़ा OOC कोड:

#include <stdio.h>

struct Node {
    int somevar;
};

void print() {
    printf("Hello from an object-oriented C method!");
};

struct Tree {
    struct Node * NIL;
    void (*FPprint)(void);
    struct Node *root;
    struct Node NIL_t;
} TreeA = {&TreeA.NIL_t,print};

int main()
{
    struct Tree TreeB;
    TreeB = TreeA;
    TreeB.FPprint();
    return 0;
}

5

मैं इसे एक साल से खोद रहा हूं:

चूंकि Gobject सिस्टम का शुद्ध C के साथ उपयोग करना कठिन है, इसलिए मैंने O के साथ C की शैली को आसान बनाने के लिए कुछ अच्छे मैक्रोज़ लिखने की कोशिश की।

#include "OOStd.h"

CLASS(Animal) {
    char *name;
    STATIC(Animal);
    vFn talk;
};
static int Animal_load(Animal *THIS,void *name) {
    THIS->name = name;
    return 0;
}
ASM(Animal, Animal_load, NULL, NULL, NULL)

CLASS_EX(Cat,Animal) {
    STATIC_EX(Cat, Animal);
};
static void Meow(Animal *THIS){
    printf("Meow!My name is %s!\n", THIS->name);
}

static int Cat_loadSt(StAnimal *THIS, void *PARAM){
    THIS->talk = (void *)Meow;
    return 0;
}
ASM_EX(Cat,Animal, NULL, NULL, Cat_loadSt, NULL)


CLASS_EX(Dog,Animal){
    STATIC_EX(Dog, Animal);
};

static void Woof(Animal *THIS){
    printf("Woof!My name is %s!\n", THIS->name);
}

static int Dog_loadSt(StAnimal *THIS, void *PARAM) {
    THIS->talk = (void *)Woof;
    return 0;
}
ASM_EX(Dog, Animal, NULL, NULL, Dog_loadSt, NULL)

int main(){
    Animal *animals[4000];
    StAnimal *f;
    int i = 0;
    for (i=0; i<4000; i++)
    {
        if(i%2==0)
            animals[i] = NEW(Dog,"Jack");
        else
            animals[i] = NEW(Cat,"Lily");
    };
    f = ST(animals[0]);
    for(i=0; i<4000; ++i) {
        f->talk(animals[i]);
    }
    for (i=0; i<4000; ++i) {
        DELETE0(animals[i]);
    }
    return 0;
}

यहाँ मेरा प्रोजेक्ट साइट है (मेरे पास en doc लिखने के लिए पर्याप्त समय नहीं है, हालाँकि चीनी में doc ज्यादा बेहतर है)।

OOC-जीसीसी


कक्षा स्थैतिक एएसएम नई DELETE अनुसूचित जनजाति ... OOC-जीसीसी में मैक्रो नहीं है
Dameng


4

C में OOP अवधारणाओं का उपयोग करने के लिए कौन से लेख या किताबें अच्छी हैं?

डेव हैन्सन के सी इंटरफेस और कार्यान्वयन है उत्कृष्ट कैप्सूलीकरण और नामकरण पर और समारोह संकेत के उपयोग पर बहुत अच्छा। डेव विरासत के अनुकरण की कोशिश नहीं करते हैं।


4

ओओपी केवल एक प्रतिमान है जो कार्यक्रमों में कोड की तुलना में अधिक महत्वपूर्ण के रूप में स्थान देता है। OOP एक भाषा नहीं है। तो, जैसे सादे C एक सरल भाषा है, सादे C में OOP भी सरल है।


3
अच्छी तरह से कहा, लेकिन यह टिप्पणी की जानी चाहिए।
pqsk

4

एक चीज जो आप करना चाहते हैं, वह एक्स विंडो के लिए Xt टूलकिट के कार्यान्वयन पर गौर करना चाहिए । यकीन है कि यह दाँत में लंबे समय से हो रहा है, लेकिन उपयोग किए जाने वाले कई ढांचे पारंपरिक सी के भीतर एक ओओ फैशन में काम करने के लिए डिज़ाइन किए गए थे। आम तौर पर इसका मतलब है कि यहां और वहां अप्रत्यक्षता की एक अतिरिक्त परत को जोड़ना और एक दूसरे पर बिछाने के लिए संरचनाओं को डिजाइन करना।

आप वास्तव में O के रास्ते में C पर इस तरह से बहुत कुछ कर सकते हैं, भले ही यह कुछ समय ऐसा लगता हो, OO अवधारणाओं ने वसंत के दिमाग से पूरी तरह से गठन नहीं किया था #include<favorite_OO_Guru.h>। उन्होंने वास्तव में उस समय के कई स्थापित सर्वोत्तम अभ्यासों का गठन किया। OO भाषाएँ और प्रणालियाँ दिन के प्रोग्रामिंग ज़ेगेटिस्ट के केवल आसुत और प्रवर्धित भाग हैं।


4

प्रश्न का उत्तर 'हां, आप कर सकते हैं' है।

ऑब्जेक्ट-ओरिएंटेड C (OOC) किट उन लोगों के लिए है जो ऑब्जेक्ट-ओरिएंटेड तरीके से प्रोग्राम करना चाहते हैं, लेकिन अच्छे पुराने C पर भी चिपक जाते हैं। OOC लागू वर्गों, एकल और कई विरासत, अपवाद हैंडलिंग।

विशेषताएं

• केवल सी मैक्रोज़ और फ़ंक्शन का उपयोग करता है, कोई भाषा एक्सटेंशन की आवश्यकता नहीं है! (एएनएसआई-सी)

• अपने आवेदन के लिए आसान करने के लिए पढ़ा स्रोत कोड। चीजों को यथासंभव सरल बनाने के लिए देखभाल की गई थी।

• कक्षाओं का एकल वंशानुक्रम

• इंटरफेस और मिक्सिंस द्वारा एकाधिक वंशानुक्रम (संस्करण 1.3 से)

• अपवादों को लागू करना (शुद्ध C में!)

• कक्षाओं के लिए आभासी कार्य

• आसान वर्ग कार्यान्वयन के लिए बाहरी उपकरण

अधिक जानकारी के लिए, http://ooc-coding.sourceforge.net/ पर जाएं ।


4

ऐसा लगता है कि लोग सी + + शैली का अनुकरण करने की कोशिश कर रहे हैं। सी। मेरा उपयोग यह है कि ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग सी करना वास्तव में स्ट्रक्चर-ओरिएंटेड प्रोग्रामिंग कर रहा है। हालाँकि, आप लेट बाइंडिंग, इनकैप्सुलेशन और इनहेरिटेंस जैसी चीजें हासिल कर सकते हैं। विरासत के लिए आप स्पष्ट रूप से अपने उप-संरचना में आधार संरचनाओं के लिए एक सूचक को परिभाषित करते हैं और यह स्पष्ट रूप से कई विरासत का एक रूप है। आपको यह भी निर्धारित करना होगा कि क्या आपके

//private_class.h
struct private_class;
extern struct private_class * new_private_class();
extern int ret_a_value(struct private_class *, int a, int b);
extern void delete_private_class(struct private_class *);
void (*late_bind_function)(struct private_class *p);

//private_class.c
struct inherited_class_1;
struct inherited_class_2;

struct private_class {
  int a;
  int b;
  struct inherited_class_1 *p1;
  struct inherited_class_2 *p2;
};

struct inherited_class_1 * new_inherited_class_1();
struct inherited_class_2 * new_inherited_class_2();

struct private_class * new_private_class() {
  struct private_class *p;
  p = (struct private_class*) malloc(sizeof(struct private_class));
  p->a = 0;
  p->b = 0;
  p->p1 = new_inherited_class_1();
  p->p2 = new_inherited_class_2();
  return p;
}

    int ret_a_value(struct private_class *p, int a, int b) {
      return p->a + p->b + a + b;
    }

    void delete_private_class(struct private_class *p) {
      //release any resources
      //call delete methods for inherited classes
      free(p);
    }
    //main.c
    struct private_class *p;
    p = new_private_class();
    late_bind_function = &implementation_function;
    delete_private_class(p);

साथ संकलित करें c_compiler main.c inherited_class_1.obj inherited_class_2.obj private_class.obj

तो सलाह यह है कि शुद्ध सी शैली से चिपके रहना चाहिए और सी ++ शैली में मजबूर करने की कोशिश नहीं करनी चाहिए। इसके अलावा यह एक एपीआई के निर्माण का एक बहुत ही साफ तरीका है।


इनहेरिटेंस के लिए आम तौर पर बेस क्लास या इंस्टेंस संरचना को व्युत्पन्न एक में एम्बेड किया जाता है, अलग से आवंटित नहीं किया जाता है और पॉइंटर्स का उपयोग किया जाता है। इस तरह से सबसे ऊपरी आधार हमेशा अपने किसी भी प्रकार की संरचना की शुरुआत में होता है, इसलिए उन्हें एक-दूसरे को आसानी से डाला जा सकता है, जो आप उन बिंदुओं के साथ नहीं कर सकते हैं जो किसी भी ऑफसेट पर हो सकते हैं।
अंडरस्कोर_ड

2

सी। में ओओपी पर एक और मोड़ के लिए http://slkpg.byethost7.com/instance.html देखें । यह सिर्फ देशी सी का उपयोग करके पुनर्संयोजन के लिए उदाहरण डेटा पर जोर देता है। मल्टीपल इनहेरिटेंस फ़ंक्शन रैपर्स का उपयोग करके मैन्युअल रूप से किया जाता है। प्रकार की सुरक्षा बनाए रखी जाती है। यहाँ एक छोटा सा नमूना है:

typedef struct _peeker
{
    log_t     *log;
    symbols_t *sym;
    scanner_t  scan;            // inherited instance
    peek_t     pk;
    int        trace;

    void    (*push) ( SELF *d, symbol_t *symbol );
    short   (*peek) ( SELF *d, int level );
    short   (*get)  ( SELF *d );
    int     (*get_line_number) ( SELF *d );

} peeker_t, SlkToken;

#define push(self,a)            (*self).push(self, a)
#define peek(self,a)            (*self).peek(self, a)
#define get(self)               (*self).get(self)
#define get_line_number(self)   (*self).get_line_number(self)

INSTANCE_METHOD
int
(get_line_number) ( peeker_t *d )
{
    return  d->scan.line_number;
}

PUBLIC
void
InitializePeeker ( peeker_t  *peeker,
                   int        trace,
                   symbols_t *symbols,
                   log_t     *log,
                   list_t    *list )
{
    InitializeScanner ( &peeker->scan, trace, symbols, log, list );
    peeker->log = log;
    peeker->sym = symbols;
    peeker->pk.current = peeker->pk.buffer;
    peeker->pk.count = 0;
    peeker->trace = trace;

    peeker->get_line_number = get_line_number;
    peeker->push = push;
    peeker->get = get;
    peeker->peek = peek;
}

2

मुझे पार्टी में थोड़ी देर हो गई है, लेकिन मैं अपने अनुभव को विषय पर साझा करना चाहता हूं: मैं इन दिनों एम्बेडेड सामान के साथ काम करता हूं, और मेरे पास एकमात्र (विश्वसनीय) संकलक सी है, जिससे मैं ऑब्जेक्ट-ओरिएंटेड लागू करना चाहता हूं सी में लिखी मेरी एम्बेडेड परियोजनाओं में दृष्टिकोण

मैंने अभी तक देखे गए अधिकांश समाधान टाइपकास्ट का भारी उपयोग किया है, इसलिए हम टाइप सुरक्षा खो देते हैं: यदि आप कोई गलती करते हैं तो कंपाइलर आपकी मदद नहीं करेगा। यह पूरी तरह से अस्वीकार्य है।

आवश्यकताएँ जो मेरे पास हैं:

  • जितना संभव हो टाइपकास्ट से बचें, इसलिए हम प्रकार की सुरक्षा नहीं खोते हैं;
  • बहुरूपता: हमें आभासी तरीकों का उपयोग करने में सक्षम होना चाहिए, और वर्ग के उपयोगकर्ता को यह पता नहीं होना चाहिए कि कुछ विशेष विधि आभासी है या नहीं;
  • मल्टीपल इनहेरिटेंस: मैं अक्सर इसका इस्तेमाल नहीं करता, लेकिन कभी-कभी मैं वास्तव में कुछ क्लास को कई इंटरफेस लागू करना चाहता हूं (या कई सुपरक्लास को बढ़ाने के लिए)।

मैंने इस लेख में विस्तार से अपना दृष्टिकोण समझाया है: सी में ऑब्जेक्ट-ओरिएंटेड प्रोग्रामिंग ; इसके अलावा, आधार और व्युत्पन्न वर्गों के लिए बॉयलरप्लेट कोड के ऑटोगेनेरेशन के लिए एक उपयोगिता है।


2

मैंने एक छोटी सी लाइब्रेरी बनाई जहाँ मैंने कोशिश की और मेरे लिए यह अच्छी तरह से काम करता है। इसलिए मैंने सोचा कि मैं अनुभव साझा करता हूं।

https://github.com/thomasfuhringer/oxygen

एकल वंशानुक्रम को आसानी से एक संरचना का उपयोग करके और इसे हर दूसरे बच्चे के वर्ग के लिए विस्तारित किया जा सकता है। मूल संरचना के लिए एक सरल कलाकार सभी वंशजों पर मूल तरीकों का उपयोग करना संभव बनाता है। जब तक आप जानते हैं कि एक चर इस तरह की एक वस्तु को पकड़े हुए एक संरचना को इंगित करता है जिसे आप हमेशा रूट क्लास में डाल सकते हैं और आत्मनिरीक्षण कर सकते हैं।

जैसा कि उल्लेख किया गया है, आभासी तरीके कुछ पेचीदा हैं। लेकिन वे करने योग्य हैं। चीजों को सरल रखने के लिए, मैं सिर्फ कक्षा विवरण संरचना में कार्यों की एक सरणी का उपयोग करता हूं जो कि प्रत्येक बच्चे की कक्षा की प्रतियां और जहां आवश्यक हो, व्यक्तिगत स्लॉट्स को फिर से खोलती है।

एकाधिक वंशानुक्रम लागू करने के लिए जटिल होगा और एक महत्वपूर्ण प्रदर्शन प्रभाव के साथ आता है। इसलिए मैं इसे छोड़ देता हूं। मैं इसे वास्तविक जीवन की परिस्थितियों को साफ-सुथरा बनाने के लिए काफी मामलों में वांछनीय और उपयोगी मानता हूं, लेकिन शायद 90% मामलों में एकल वंशानुक्रम जरूरतों को कवर करता है। और एकल विरासत सरल है और कुछ भी नहीं खर्च होता है।

इसके अलावा मुझे टाइप सेफ्टी की परवाह नहीं है। मुझे लगता है कि आपको प्रोग्रामिंग गलतियों से बचाने के लिए आपको कंपाइलर पर निर्भर नहीं होना चाहिए। और यह आपको केवल त्रुटियों के एक छोटे से हिस्से से ही ढाल देता है।

आमतौर पर, एक वस्तु उन्मुख वातावरण में आप स्मृति प्रबंधन को संभव तक सीमित करने के लिए संदर्भ गिनती को लागू करना चाहते हैं। इसलिए मैंने "ऑब्जेक्ट" रूट क्लास में एक संदर्भ गणना और कुछ मेमोरी को ढेर मेमोरी के आवंटन और निपटान के लिए रखा।

यह सब बहुत ही सरल और दुबला है और मुझे OO की अनिवार्यता देता है, बिना मुझे उस राक्षस से निपटने के लिए मजबूर करता है जो C ++ है। और मैं सी भूमि में रहने के लचीलेपन को बनाए रखता हूं, जो अन्य चीजों के बीच तीसरे पक्ष के पुस्तकालयों को एकीकृत करना आसान बनाता है।


1

मैं उद्देश्य-सी का उपयोग करने का प्रस्ताव करता हूं, जो सी का सुपरसेट है।

जबकि Objective-C 30 वर्ष पुराना है, यह सुरुचिपूर्ण कोड लिखने की अनुमति देता है।

http://en.wikipedia.org/wiki/Objective-C


उस स्थिति में मैं C ++ की सिफारिश करूंगा क्योंकि इसके वास्तव में ऑब्जेक्ट ओरिएंटेड है ...
yyny

यह कोई उत्तर नहीं है। लेकिन वैसे भी, @YoYoYonnY: मैं ऑब्जेक्टिव-सी का उपयोग नहीं करता हूं और सी ++ का उपयोग करता हूं, लेकिन इस तरह की टिप्पणियां बिना आधार के उपयोग की हैं, और आपने कोई भी प्रदान नहीं किया है। आप दावा क्यों करते हैं कि ऑब्जेक्ट-सी "वास्तव में ऑब्जेक्ट ओरिएंटेड ..." होने से कम हो जाता है? और C ++ सफल क्यों होता है जहां ऑब्जेक्टिव-सी फेल होता है। मजेदार बात यह है कि वस्तुनिष्ठ-सी, ठीक है, का शाब्दिक अर्थ है इसके नाम में वस्तु , जबकि C ++ एक बहु-प्रतिमान भाषा के रूप में खुद को बाजार देता है, एक OOP एक नहीं (यानी मुख्य रूप से OOP नहीं, और कुछ बल्कि चरम लोक दृश्य ओओपी में है) सब पर) ... तो क्या आप सुनिश्चित हैं कि आप उन नामों को गलत तरीके से गोल नहीं कर पाए हैं?
अंडरस्कोर_ड

0

हां, लेकिन मैंने कभी किसी को सी के साथ किसी भी तरह के बहुरूपता को लागू करने का प्रयास करते नहीं देखा।


6
आपको और अधिक देखने की आवश्यकता है :) उदाहरण के लिए, माइक्रोसॉफ्ट के डायरेक्ट एक्स में एक पॉलीमॉर्फिक सी इंटरफ़ेस है।
आशुली 19

8
उदाहरण के लिए लिनक्स कर्नेल कार्यान्वयन में देखें। यह सी। में बहुत आम और व्यापक रूप से इस्तेमाल किया जाने वाला अभ्यास है
इल्या

3
ग्लिब भी बहुरूपी है, या बहुरूपता की अनुमति देने वाले तरीके से इस्तेमाल किया जा सकता है (यह C ++ की तरह है जिसे आपको स्पष्ट रूप से कहना है कि कौन से कॉल आभासी हैं)
Spudd86

1
बहुरूपता सी में दुर्लभ नहीं है, दूसरी ओर कई विरासत है।
जोहान Bjäreholt
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.