কীভাবে একজন সি-তে অবজেক্ট-ওরিয়েন্টেড কোড লিখবেন? [বন্ধ]


499

সিটিতে অবজেক্ট-ভিত্তিক কোড লেখার কয়েকটি উপায় কী কী? বিশেষত বহুত্ববাদ সম্পর্কে।


এই স্ট্যাক ওভারফ্লো প্রশ্নটি সিটিতে অবজেক্ট-ওরিয়েন্টেশনটিও দেখুন


1
<a href=" ldeniau.web.cern.ch/ldeniau/html/oopc.html "> সি তে অবজেক্ট ওরিয়েন্টড প্রোগ্রামিং </a> লরেন্ট ডেনিয়াউ দ্বারা


25
@ ক্যামিলো মার্টিন: আমি ইচ্ছাকৃতভাবে জিজ্ঞাসা করেছি যে এটি করা উচিত নয় । আমি সি তে ওওপি ব্যবহার করতে আগ্রহী নই তবে যাইহোক, সি তে ওও সমাধানগুলি দেখে, আমি / আমরা সি এর সীমাবদ্ধতা এবং / অথবা নমনীয়তা এবং পলিমারফিজম প্রয়োগ এবং ব্যবহারের সৃজনশীল উপায়গুলি সম্পর্কে আরও জানতে আগ্রহী stand
দিনাহ

5
ওও কেবল একটি প্যাটার্ন। এখানে চেক করুন, এটি .bat ফাইলগুলিতেও করা যেতে পারে : dirk.rave.org/chap9.txt (আপনি যদি যথেষ্ট আগ্রহী হন তবে যে কোনও প্রোগ্রামিং ভাষায় কোনও প্যাটার্ন প্রয়োগ করা যেতে পারে), আমার ধারণা। যদিও এটি চিন্তার জন্য ভাল খাবার। এবং সম্ভবত আমরা সেগুলিতে নেই এমন ভাষাগুলি মঞ্জুর করে এমন ধরণগুলি প্রয়োগ করে অনেক কিছু শিখতে পারি।
ক্যামিলো মার্টিন

6
জিটিকে - 'স্কিউজ মি, জিবজেক্ট - আসলে সি-ও-ওপোর (সার্টা) এর খুব ভাল উদাহরণ So
new123456

উত্তর:


361

হ্যাঁ. প্রকৃতপক্ষে অ্যাক্সেল শ্রেইনার তাঁর "অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিং ইন এএনএসআই-সি" বইটি বিনামূল্যে সরবরাহ করেছেন যা বিষয়টিকে পুরোপুরিভাবে কভার করে।


28
যদিও এই বইয়ের ধারণাগুলিগুলি সলিড, আপনি ধরণের সুরক্ষা হারাবেন।
ডায়াপির

22
আমরা নকশার নিদর্শন হিসাবে যা জানি, তার আগে ডিজাইনের প্যাটার্নটি "অবজেক্ট অরিয়েন্টেশন" নামে পরিচিত; আবর্জনা সংগ্রহের সাথে একই রকম এবং অন্যান্য। এগুলি এখন এতটা সংক্রামিত, আমরা ভুলে যেতে ঝোঁক, যখন তারা প্রথম পরিকল্পনা করা হয়েছিল, এটি অনেকটা একইভাবে ছিল যা আমরা আজ ডিজাইনের নিদর্শন হিসাবে বিবেচনা করি
ডিজিন

11
আপনি এটি সরাসরি লেখকের সাইট থেকে পেতে পারেন: cs.rit.edu/~ats/books/ooc.pdf একই লেখকের অন্যান্য কাগজপত্র: cs.rit.edu/~ats/books/index.html
pakman

10
যথাযথ সংগ্রহ (বুক + উত্স-কোড উদাহরণগুলি) এই রিট থেকে পাওয়া যায় AN এডু সূচক এএনএসআই-সি এর সাথে অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিং
ডেভিড সি র্যাঙ্কিন

3
এই বইটি কি সমকালীন পর্যালোচনা করা হয়েছে? প্রথম পৃষ্ঠার প্রথম অনুচ্ছেদের প্রথম বাক্যে একটি টাইপো রয়েছে।
ডাগ্রুমগুলি

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;

অবশ্যই, উপরের এই কোড বিভাগগুলি আসলে "কনস্ট্রাক্টর" এর মধ্যে থাকবে in rs232Init()

আপনি যখন সেই শ্রেণি থেকে 'উত্তরাধিকারী' হন, আপনি কেবলমাত্র নিজের ক্রিয়াকলাপের দিকে নির্দেশ করতে পয়েন্টার পরিবর্তন করেন। যারা এই ফাংশনগুলি বলে তাদের সবাই ফাংশন পয়েন্টারগুলির মাধ্যমে এটি করবে আপনার পলিমারফিজম:

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

ম্যানুয়াল ভিটেবলের মতো বাছাই করুন।

এমনকি আপনি ন্যূনালএল-তে পয়েন্টার সেট করে ভার্চুয়াল ক্লাসও করতে পারতেন - আচরণটি সি ++ এর থেকে কিছুটা আলাদা হবে (সংকলনের সময় ত্রুটির পরিবর্তে রান-টাইমে একটি কোর ডাম্প)।

এখানে নমুনা কোডের একটি অংশ যা এটি দেখায়। প্রথম শীর্ষ স্তরের শ্রেণিবদ্ধ:

#include <stdio.h>

// The top-level class.

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

তারপরে আমাদের টিসিপি 'সাবক্লাস' এর কাজ রয়েছে:

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

এবং এইচটিটিপি এক হিসাবে:

// 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 চমৎকার উদাহরণ! যদিও কেউ যদি সত্যিই এই রাস্তা নিচে যেতে চায়, তার জন্য আরো উপযুক্ত হবে "উদাহরণস্বরূপ" structs একটি আছে একক ক্ষেত্র তাদের "ভার্চুয়াল সারণী" উদাহরণ হিসেবে বলা যায় নির্দেশিত এক জায়গায় যে টাইপ জন্য সব ভার্চুয়াল ফাংশন রয়েছে। অর্থাৎ আপনার tCommClassনামটি পুনরায় নামকরণ করা হবে tCommVTএবং কোনও tCommClassস্ট্রাক্টে কেবলমাত্র ডেটা ক্ষেত্র এবং tCommVT vt"একমাত্র এবং কেবলমাত্র" ভার্চুয়াল-টেবিলের দিকে নির্দেশ করে একটি একক ক্ষেত্র থাকবে have প্রতিটি দৃষ্টান্তের সাথে চারদিকে সমস্ত পয়েন্টার বহন করা অপ্রয়োজনীয় ওভারহেড যুক্ত করে এবং আপনি সি ++, আইএমএইচও-র চেয়ে জাভাস্ক্রিপ্টে কীভাবে স্টাফ করবেন তা আরও সাদৃশ্যপূর্ণ।
গ্রু

1
সুতরাং এটি একটি একক ইন্টারফেসের বাস্তবায়ন দেখায়, তবে একাধিক ইন্টারফেস বাস্তবায়ন সম্পর্কে কী? নাকি একাধিক উত্তরাধিকার?
weberc2

ওয়েবার, আপনি যদি সি ++ এর সমস্ত কার্যকারিতা চান তবে আপনার সম্ভবত সি ++ ব্যবহার করা উচিত। পলিমারফিজম সম্পর্কে আলাদাভাবে "ফর্ম" নেওয়ার বস্তুর দক্ষতা সম্পর্কে প্রশ্নটি বিশেষভাবে জিজ্ঞাসা করেছিল। আপনি অবশ্যই সি তে ইন্টারফেস এবং একাধিক উত্তরাধিকার করতে পারেন তবে এটি অতিরিক্ত কাজের একটি ন্যায্য বিষয়, এবং আপনাকে সি ++ অন্তর্নির্মিত স্টাফ ব্যবহার না করে নিজেকে স্মার্টগুলি পরিচালনা করতে হবে।
প্যাক্সিডিয়াবল

86

নেমস্পেসগুলি প্রায়শই করে করা হয়:

stack_push(thing *)

পরিবর্তে

stack::push(thing *)

একটি তৈরি করতে হলে সি একটি ভালো কিছু মধ্যে struct হয় সি ++ বর্গ আপনি চালু করতে পারেন:

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
}

আমি ডেস্ট্রাক্টর বা মুছে ফেলিনি, তবে এটি একই ধাঁচ অনুসরণ করে।

এই_এই_এখানে_আস_আন_ উদাহরণ_একটি স্ট্যাটিক ক্লাস ভেরিয়েবলের মতো - এক ধরণের সমস্ত দৃষ্টান্তের মধ্যে ভাগ করে নেওয়া। সমস্ত পদ্ধতি সত্যই স্থিতিশীল, ব্যতীত কিছু এটি * নেয়


1
@ শ্রেণিবদ্ধ - এর st->my_type->push(st, thing2);পরিবর্তেst->my_type.push(st, thing2);
ফ্যাব্রিকিও

@ শ্রেণিবদ্ধ: অথবা এর struct stack_type my_type; পরিবর্তেstruct stack_type * my_type;
ফ্যাব্রিকিও

3
আমি ক্লাসের জন্য একটি কাঠামো থাকার ধারণা পছন্দ করি। তবে জেনেরিক Classস্ট্রাক্ট কেমন? এটি ওও সি সি ++ এর চেয়ে আরও গতিশীল করে তুলবে । কীভাবে? যাইহোক, +1।
লিনাকিনিওস

54

আমি বিশ্বাস করি যে এটি নিজস্বভাবে কার্যকর হওয়ার পাশাপাশি সি-তে ওওপি বাস্তবায়ন করা ওওপি শেখার এবং এর অভ্যন্তরীণ কার্যকারিতা বোঝার একটি দুর্দান্ত উপায় । অনেক প্রোগ্রামারদের অভিজ্ঞতা দেখিয়েছে যে দক্ষতার সাথে এবং আত্মবিশ্বাসের সাথে কোনও কৌশল ব্যবহার করতে একজন প্রোগ্রামারকে অবশ্যই বুঝতে হবে যে অন্তর্নিহিত ধারণাগুলি কীভাবে চূড়ান্তভাবে প্রয়োগ করা হয়। সি তে অনুকরণকারী ক্লাস, উত্তরাধিকার এবং পলিমারফিজম কেবল এটি শেখায়।

মূল প্রশ্নের উত্তর দেওয়ার জন্য, এখানে কয়েকটি সংস্থান দেওয়া আছে যা সিতে ওওপি কীভাবে করতে হয় তা শেখায়:

EmbeddedGurus.com ব্লগ পোস্টে দেখায় কিভাবে ক্লাস এবং পোর্টেবল সি একক উত্তরাধিকার বাস্তবায়ন "সি মধ্যে অবজেক্ট-ভিত্তিক প্রোগ্রামিং": 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_3.0.zip থেকে পাওয়া যায়


4
সি + ম্যানুয়ালটির জন্য নতুন ইউআরএল: state-machine.com/doc/cplus_3.0_manual.pdf
লিয়াং

32

আমি এটা সম্পন্ন দেখেছি। আমি এটি সুপারিশ করব না। সি ++ প্রাথমিকভাবে এইভাবে একটি প্রিপ্রসেসর হিসাবে শুরু করেছিলেন যা মধ্যবর্তী পদক্ষেপ হিসাবে সি কোড তৈরি করে।

মূলত আপনি যা করছেন তা হ'ল আপনার ফাংশনের রেফারেন্সগুলি সংরক্ষণ করার জন্য আপনার সমস্ত পদ্ধতির জন্য প্রেরণ টেবিল তৈরি করা। কোনও শ্রেণীর বিভাজন জানানোতে এই প্রেরণের টেবিলটি অনুলিপি করা এবং আপনি যে নতুন প্রবেশপথকে ওভাররাইড করতে চেয়েছিলেন তা প্রতিস্থাপন করতে পারে, যদি আপনার নতুন "পদ্ধতিগুলি" বেস পদ্ধতিটি চালু করতে চায় তবে মূল পদ্ধতিটি কল করতে হবে। অবশেষে, আপনি সি ++ এর পুনর্লিখন শেষ করবেন।


5
"অবশেষে, আপনি পুনরায় লেখার সি ++ শেষ করেছেন" আমি ভাবছিলাম / যদি আশংকা থাকে যে ঘটনাটি ঘটবে।
দিনাহ

39
অথবা, আপনি অবজেক্টিভ সি পুনর্লিখন শেষ করতে পারেন, যা অনেক বেশি আকর্ষণীয় ফলাফল হবে।
অধ্যাপক ফ্যালকেন চুক্তি লঙ্ঘন

3
সেখানে গলি, যেমন বর্গ-কম গন্ধ হয় জাভাস্ক্রিপ্ট মধ্যে , যেখানে গুরু বলছে: "। আমরা ক্লাস প্রয়োজন হবে না অনুরূপ বস্তু প্রচুর করতে" তবে আমি আশঙ্কা করি সি তে এটি অর্জন করা সহজ নয় (যদিও) এখনও বলার মতো অবস্থানে নেই। (স্ট্রাক্ট ক্লোন করার জন্য কি কোনও ক্লোন () রুটিন আছে?)
লুমি

1
আর একজন স্মার্ট ছেলেরা, যাকে বাস্তবে এটি বাস্তবায়ন করতে হয়েছিল এবং সেই বাস্তবায়ন দ্রুত করতে হয়েছিল (গুগল, ভি 8 ইঞ্জিন) সমস্ত কিছু জাভাস্ক্রিপ্টে ফিরে (লুকানো) ক্লাস যুক্ত করেছে।
cubspl42

glibসিতে উদ্দেশ্যমূলকভাবে লেখা হয় না ?
ক্রাভেমির

26

নিশ্চিত যে সম্ভব। এটি জিওজেক্ট , ফ্রেমওয়ার্ক যা সমস্ত জিটিকে + করে এবং GNOME- র নির্ভর করে, যা করে।


এই জাতীয় পদ্ধতির পক্ষে কি কি? অর্থাৎ। এটি C ++ ব্যবহার করে লেখা অনেক সহজ।
ক্রাভেমির

@ ক্রাভেমির ওয়েল, সি ++ সি হিসাবে যথেষ্ট পোর্টেবল নয় এবং সি ++ এর কোডের সাথে লিঙ্ক করা কিছুটা শক্ত যা অন্য সি ++ কম্পাইলার দ্বারা সংকলিত হতে পারে। তবে হ্যাঁ, সি ++ তে ক্লাসগুলি লেখা আরও সহজ, যদিও GObject আসলেই এতটা কঠিন নয় (ধরে নিই যে আপনি কিছুটা বয়লার প্লেট আপত্তি করেন না)।
এডউইন বাক

17

সি স্টিডিও ফাইল সাব-লাইব্রেরি আনড্রাক্ট্রেটেড সি-তে কীভাবে বিমূর্ততা, এনক্যাপসুলেশন এবং মডুলারিটি তৈরি করতে পারে তার একটি দুর্দান্ত উদাহরণ is

উত্তরাধিকার এবং বহুবিকতা - অন্যান্য দিকগুলি প্রায়শই ওওপি-র প্রয়োজনীয় হিসাবে বিবেচিত হয় - তারা যে প্রতিশ্রুতি দেয় উত্পাদনশীলতা লাভগুলি সরবরাহ করে না এবং যুক্তিযুক্ত যুক্তি তৈরি করা হয়েছে যে তারা আসলে সমস্যার ডোমেন সম্পর্কে বিকাশ এবং চিন্তাভাবনায় বাধা দিতে পারে।


স্ট্যান্ডিও কার্নেল স্তরটিতে বিমূর্ত নয়? যদি আমি ভুল না হয়ে থাকি, সি-লাইব্রেরি তাদের সাথে চরিত্রের ফাইল / ডিভাইস হিসাবে বিবেচনা করে এবং কার্নেল ড্রাইভাররা কাজটি করে, ...
ক্রাভেমির

15

একটি প্রাণী এবং কুকুরের সাথে তুচ্ছ উদাহরণ: আপনি সি ++ এর ভিটিবেল প্রক্রিয়া (মূলত যাইহোক) মিরর করুন। আপনি বরাদ্দ এবং ইনস্ট্যান্টেশন পৃথক করেও (এনিমেল_আলোক, এনিমেল_নিউ) যাতে আমরা একাধিকবার ম্যালোক () কল করি না। আমাদের অবশ্যই স্পষ্টভাবে পাস করতে হবেthis চারপাশে পয়েন্টারটি হবে।

আপনি যদি অ-ভার্চুয়াল ফাংশনগুলি করতে চান তবে এটি ট্রিভাল। আপনি কেবল সেগুলি ভিটিবেলে যোগ করবেন না এবং স্থির ফাংশনগুলির একটির প্রয়োজন হয় নাthis পয়েন্টারের । অস্পষ্টতাগুলি সমাধান করার জন্য একাধিক উত্তরাধিকারের জন্য সাধারণত একাধিক ভ্যাটবিলের প্রয়োজন হয়।

এছাড়াও, ব্যতিক্রম হ্যান্ডলিং করতে আপনার সেটজেম্প / লংজ্যাম্প ব্যবহার করতে সক্ষম হওয়া উচিত।

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

পুনশ্চ. এটি একটি সি ++ সংকলকটিতে পরীক্ষা করা হয় তবে এটি সি সংকলকটিতে কাজ করা সহজ হওয়া উচিত।


typedefএ এর অভ্যন্তরে structসি তে সম্ভব নয়
মাসউদ

13

পরীক্ষা করে দেখুন GObject । এটি সি এর ওও হতে হবে এবং আপনি যা সন্ধান করছেন তার একটি বাস্তবায়ন। আপনি যদি সত্যিই ওও চান, তবে সি ++ বা অন্য কোনও ওওপি ভাষার সাথে যান। আপনি যদি ওও ভাষাগুলির সাথে ডিল করতে অভ্যস্ত হন তবে GObject এর সাথে কাজ করা সত্যিই কঠিন হতে পারে তবে কোনও কিছুর মতোই আপনি সম্মেলন এবং প্রবাহে অভ্যস্ত হয়ে যাবেন।


12

এটি পড়া আকর্ষণীয় হয়েছে। আমি নিজেই একই প্রশ্নটি ভাবছি এবং এটি সম্পর্কে চিন্তাভাবনার সুবিধাগুলি হ'ল:

  • অপ-ওওপি ভাষায় কীভাবে ওওপি ধারণাগুলি প্রয়োগ করা যায় তা কল্পনা করার চেষ্টা করা আমাকে ওওপি ভাষার শক্তি বুঝতে সহায়তা করে (আমার ক্ষেত্রে, সি ++)। প্রদত্ত প্রকারের অ্যাপ্লিকেশনটির জন্য সি বা সি ++ ব্যবহার করবেন কিনা সে সম্পর্কে এটি আমাকে আরও ভাল রায় দিতে সহায়তা করে - যেখানে একটির সুবিধাগুলি অপরটির চেয়ে বেশি ওজনযুক্ত।

  • এই সম্পর্কিত তথ্য এবং মতামতের জন্য আমার ওয়েব ব্রাউজিংয়ে আমি এমন একজন লেখককে পেয়েছি যিনি এমবেডেড প্রসেসরের জন্য কোড লিখছিলেন এবং কেবলমাত্র একটি সি সংকলক উপলব্ধ ছিল: http://www.eetimes.com/discussion/other/4024626/Object- ওরিয়েন্টড -C-তৈরি করা-ফাউন্ডেশন-ক্লাস-পার্ট -1

তার ক্ষেত্রে, প্লেইন সি-তে OOP ধারণাগুলি বিশ্লেষণ ও মানিয়ে নেওয়া একটি বৈধ অনুসারী ছিল। দেখা যাচ্ছে যে ওভারহেডের পারফরম্যান্সের কারণে সিটিতে সেগুলি প্রয়োগ করার চেষ্টা করার ফলে তিনি কিছু ওওপি ধারণার ত্যাগ করতে প্রস্তুত ছিলেন them

আমি যে পাঠ গ্রহণ করেছি তা হ্যাঁ এটি একটি নির্দিষ্ট ডিগ্রিতে করা যেতে পারে এবং হ্যাঁ, এটি চেষ্টা করার কিছু ভাল কারণ রয়েছে।

শেষ পর্যন্ত, মেশিনটি স্ট্যাক পয়েন্টার বিটগুলিকে ঝাঁকুনি দিচ্ছে, যা প্রোগ্রামটিকে পাল্টা ঝাঁপ দাও এবং মেমরি অ্যাক্সেসের ক্রিয়াকলাপ গণনা করছে। দক্ষতার দৃষ্টিকোণ থেকে, আপনার প্রোগ্রাম দ্বারা এই গণনাগুলির যত কম হয়েছে, তত ভাল ... তবে কখনও কখনও আমাদের কেবল এই কর দিতে হয় যাতে আমরা আমাদের প্রোগ্রামটি এমনভাবে পরিচালনা করতে পারি যা এটি মানুষের ত্রুটির পক্ষে কমপক্ষে সংবেদনশীল হয়ে ওঠে। ওওপি ভাষা সংকলক উভয় দিক অপ্টিমাইজ করার চেষ্টা করে। প্রোগ্রামারকে সি এর মতো ভাষায় এই ধারণাগুলি বাস্তবায়নে আরও বেশি যত্নবান হতে হবে


10

অ্যাপল এর কোর ফাউন্ডেশন সেট এর API এর জন্য ডকুমেন্টেশনগুলি দেখতে আপনাকে সহায়ক হতে পারে। এটি একটি খাঁটি সি এপিআই, তবে ধরণের অনেকগুলি উদ্দেশ্য-সি অবজেক্টের সমতুল্য হয়ে থাকে।

আপনি নিজেই ওজেক্টিভ-সি এর নকশাটি দেখতে সহায়ক হতে পারেন। এটি সি ++ থেকে কিছুটা পৃথক যে বস্তুর সিস্টেমটি সি ফাংশনগুলির ক্ষেত্রে যেমন সংজ্ঞায়িত করা হয়, যেমন objc_msg_sendকোনও বস্তুর কোনও পদ্ধতিতে কল করা। সংকলকটি বর্গাকার বন্ধনী সিনট্যাক্সটিকে সেই ফাংশন কলগুলিতে অনুবাদ করে, তাই আপনাকে এটি জানতে হবে না, তবে আপনার প্রশ্ন বিবেচনা করে আপনি এটি কীভাবে হুডের নীচে কাজ করে তা শেখার পক্ষে দরকারী হতে পারে।


10

বেশ কয়েকটি কৌশল ব্যবহার করা যেতে পারে। সবচেয়ে গুরুত্বপূর্ণটি হল কীভাবে প্রকল্পটি বিভক্ত করা যায় one আমরা আমাদের প্রকল্পে একটি ইন্টারফেস ব্যবহার করি যা একটি .h ফাইলে ঘোষিত হয় এবং একটি .c ফাইলে অবজেক্টের প্রয়োগ implementation গুরুত্বপূর্ণ অংশটি হ'ল .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

সি বাস্তবায়ন ফাইলটি এরকম কিছু হবে।

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

সুতরাং আমি সেই মডিউলের প্রতিটি ফাংশনে একটি বস্তুকে স্পষ্টভাবে পয়েন্টারটি দেব poin একটি সি ++ সংকলক এটি স্পষ্টভাবে করে এবং সি তে আমরা এটি স্পষ্টভাবে লিখি।

আমি সত্যিই ব্যবহার this আমার প্রোগ্রামগুলিতে করি, এটি নিশ্চিত করার জন্য যে আমার প্রোগ্রামটি সি ++ তে সংকলন করছে না এবং এতে আমার সিনট্যাক্স হাইলাইটিং এডিটরটিতে অন্য রঙে থাকার চমৎকার সম্পত্তি রয়েছে।

এফইও_স্ট্রাক্টের ক্ষেত্রগুলি একটি মডিউলে সংশোধন করা যেতে পারে এবং অন্য মডিউলটিকে এখনও ব্যবহারযোগ্য হওয়ার জন্য পুনরায় সংকলনের প্রয়োজন হয় না।

এই শৈলীর সাহায্যে আমি ইতিমধ্যে ওওপি (ডেটা এনক্যাপসুলেশন) সুবিধার একটি বড় অংশ হ্যান্ডেল করেছি। ফাংশন পয়েন্টারগুলি ব্যবহার করে, উত্তরাধিকারের মতো কোনও কিছু কার্যকর করা এমনকি সহজ তবে সত্যই, এটি সত্যিই কেবল বিরল।


6
আপনি যদি typedef struct FOO_type FOO_typeশিরোনামটিতে শূন্যতার জন্য টাইপেফের পরিবর্তে করেন তবে আপনার কাঠামোটি প্রকাশ না করেও আপনি টাইপ চেকিংয়ের অতিরিক্ত সুবিধা পাবেন।
স্কট ওয়েলস

8

আপনি এটি ফাংশন পয়েন্টার ব্যবহার করে জাল করতে পারেন, এবং বাস্তবে, আমি মনে করি যে সি ++ প্রোগ্রামগুলি সিতে সংকলন করা তাত্ত্বিকভাবে সম্ভব is

তবে, উদাহরণস্বরূপ এমন একটি ভাষা বেছে নেওয়ার পরিবর্তে কোনও ভাষায় দৃষ্টান্ত জোর দিয়ে বোঝা যায় না।


5
প্রথম সি ++ সংকলক ঠিক তা করেছিল - এটি সি ++ কোডকে সমতুল্য (তবে কুৎসিত এবং অ-মানব-পঠনযোগ্য) সি কোডে রূপান্তরিত করে, যা সি সংকলক দ্বারা সংকলিত হয়েছিল।
অ্যাডাম রোজেনফিল্ড

2
ইডিজি, সিফ্রন্ট এবং আরও কিছু এখনও এটি করতে সক্ষম are খুব ভাল কারণ সহ: প্রতিটি প্ল্যাটফর্মের একটি সি ++ সংকলক থাকে না।
জ্যাস্পার বেকার্স

কিছু কারণে আমি ভেবেছিলাম যে সি-ফ্রন্ট কেবলমাত্র কয়েকটি সি ++ এক্সটেনশনগুলি (যেমন, রেফারেন্সগুলি) সমর্থন করে তবে পুরো ওওপি / ডায়নামিক প্রেরণ এমুলেশনটি সমর্থন করে না।
উরি

2
আপনি এলএলভিএম এবং সি ব্যাকএন্ডের সাহায্যে একই জিনিস করতে পারেন।
জিফ্রে

7

অবজেক্ট ওরিয়েন্টেড সি, কাজটি করা যেতে পারে, আমি কোরিয়ায় উত্পাদনের ক্ষেত্রে এই ধরণের কোড দেখেছি এবং আমি বছরের পর বছরগুলি দেখেছি এটি সবচেয়ে ভয়ঙ্কর দৈত্য ছিল (এটি গত বছরের মতো ছিল (2007) যে কোডটি দেখেছি)। সুতরাং হ্যাঁ এটি করা যেতে পারে, এবং হ্যাঁ লোকেরা এটি আগেও করেছিল এবং এখনও এবং এটি আজ এবং যুগেও করে। তবে আমি সি ++ বা অবজেক্টিভ-সি সুপারিশ করবো, দুটিই ভিন্ন ভিন্ন দৃষ্টান্তের সাথে অবজেক্ট অরিয়েন্টেশন দেওয়ার উদ্দেশ্যে, সি থেকে জন্ম নেওয়া ভাষা।


3
যদি লিনাস আপনার মন্তব্য দেখুন। তিনি অবশ্যই হাসবেন বা আপনাকে অভিশাপ দেবেন
Anders Lind

7

আপনি যদি নিশ্চিত হন যে সমস্যার সমাধানের জন্য আপনি একটি ওওপি পদ্ধতির চেয়েও উন্নত, তবে কেন আপনি এটি একটি অ-ওওপি ভাষায় সমাধান করার চেষ্টা করবেন? দেখে মনে হচ্ছে আপনি কাজের জন্য ভুল সরঞ্জামটি ব্যবহার করছেন। সি ++ বা অন্য কোনও অবজেক্ট-ভিত্তিক সি বৈকল্পিক ভাষা ব্যবহার করুন।

আপনি যদি জিজ্ঞাসা করছেন যে আপনি ইতিমধ্যে সিটিতে লিখিত একটি বিদ্যমান বৃহত প্রকল্পের কোডিং শুরু করছেন, তবে আপনার নিজের (বা অন্য কারও) ওওপি দৃষ্টান্তকে প্রকল্পের অবকাঠামোতে জোর করার চেষ্টা করা উচিত নয়। প্রকল্পে ইতিমধ্যে উপস্থিত নির্দেশিকা অনুসরণ করুন। সাধারণভাবে, ক্লিন এপিআই এবং বিচ্ছিন্ন লাইব্রেরি এবং মডিউলগুলি পরিষ্কার ওওপিও- ইশ ডিজাইনের দিকে অনেক এগিয়ে যাবে ।

তাহলে, এর পরে, আপনি কি সত্যিই গলি সি করছেন সেট করা, পড়া এই (পিডিএফ)।


36
সত্যই প্রশ্নের উত্তর দিচ্ছে না ...
ব্রায়ান পোস্তো

2
@ ব্রায়ান, পিডিএফ-এর লিঙ্কটি সরাসরি প্রশ্নের উত্তর দিতে উপস্থিত হবে, যদিও আমার নিজের জন্য যাচাই করার সময় নেই।
মার্ক রান্সম

5
পিডিএফ-এর লিঙ্কটি বিষয়টির পুরো পাঠ্যপুস্তক বলে মনে হচ্ছে ... একটি সুন্দর প্রমাণ, তবে এটি মার্জিনের সাথে খাপ
খায় না

5
হ্যাঁ, প্রশ্নের উত্তর দিন। কোনও ভাষা কীভাবে একটি বিশেষ উপায়ে ব্যবহার করতে হয় তা জিজ্ঞাসা করা একেবারে বৈধ। অন্যান্য ভাষায় মতামতের জন্য অনুরোধ ছিল না ....
টিম রিং

9
@ ব্রায়ান এবং টিম রিং: প্রশ্নটি কোনও বিষয়ে বইয়ের সুপারিশ চেয়েছিল ; আমি তাকে একটি বইয়ের লিঙ্ক দিয়েছিলাম যা এই বিষয়টিকে বিশেষভাবে সম্বোধন করে। সমস্যাটির দিকে নজর দেওয়া কেন সর্বোত্তম হতে পারে না সে সম্পর্কেও আমি আমার মতামত দিয়েছিলাম (যা আমি মনে করি এখানকার অনেক লোকই ভোট এবং অন্যান্য মন্তব্য / উত্তরের উপর ভিত্তি করে একমত হতে দেখছেন)। আমার উত্তরটি উন্নত করার জন্য আপনার কি কোনও পরামর্শ আছে?
RarrRarrRarr

6

হ্যা, তুমি পারো. লোকেরা সি ++ বা উদ্দেশ্য-সি এর আগে অবজেক্ট-ওরিয়েন্টেড সি লিখছিল ঘটনাস্থলে আসার লিখছিল। সি ++ এবং অবজেক্টিভ-সি উভয় অংশেই সিটিতে ব্যবহৃত কিছু ওও ধারণাগুলি গ্রহণ এবং ভাষার অংশ হিসাবে আনুষ্ঠানিক করার চেষ্টা করেছিল।

এখানে একটি খুব সহজ প্রোগ্রাম যা দেখায় আপনি কীভাবে এমন কিছু তৈরি করতে পারেন যা দেখতে দেখতে একটি পদ্ধতি কল (এটি করার আরও ভাল উপায় আছে This এটি ভাষা প্রমাণগুলি সমর্থন করার পক্ষে প্রমাণ):

#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

যোগ করার জন্য একটি ছোট ওওসি কোড:

#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

আমি এক বছর ধরে এটি খনন করছি:

জিওজেক্ট সিস্টেমটি খাঁটি সি দিয়ে ব্যবহার করা শক্ত হওয়ায় আমি সি দিয়ে ওও স্টাইলটি সহজ করতে কিছু সুন্দর ম্যাক্রো লেখার চেষ্টা করেছি I

#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। ডক লেখার জন্য আমার কাছে পর্যাপ্ত সময় নেই, তবে চীনা ভাষায় ডকটি আরও ভাল।

OOC-জিসিসি


ক্লাস স্ট্যাটিক এ এস এম নতুন DELETE এসটি ... OOC-জিসিসি মধ্যে ম্যাক্রো হয়
dameng


4

কোন নিবন্ধ বা বই সি তে ওওপি ধারণা ব্যবহার করা ভাল?

ডেভ হ্যানসনের সি ইন্টারফেস এবং ইমপ্লিমেনটেসন হয় চমৎকার এনক্যাপস্যুলেশন ও নামকরণের উপর এবং ফাংশন পয়েন্টার ব্যবহারের উপর খুব ভালো। ডেভ উত্তরাধিকার অনুকরণ করার চেষ্টা করে না।


4

ওওপি হ'ল একটি দৃষ্টান্ত যা প্রোগ্রামগুলিতে কোডের চেয়ে ডেটাকে আরও গুরুত্বপূর্ণ হিসাবে রাখে। ওওপি কোনও ভাষা নয়। সুতরাং, সরল সি যেমন সরল ভাষা, তেমন সরল সিতেও ওওপি সহজ।


3
ভাল বলেছেন, তবে এটি মন্তব্য করা উচিত।
pqsk

4

একটি জিনিস যা আপনি করতে চাইতে পারেন তা হ'ল এক্স উইন্ডোটির জন্য এক্সটি সরঞ্জামকিট বাস্তবায়ন সন্ধান করা । অবশ্যই এটি দাঁতে দীর্ঘ হয়ে চলেছে, তবে ব্যবহৃত অনেকগুলি কাঠামো traditionalতিহ্যবাহী সি এর মধ্যে ওও ফ্যাশনে কাজ করার জন্য ডিজাইন করা হয়েছিল সাধারণত এটির অর্থ এখানে এবং সেখানে একটি অতিরিক্ত স্তর যুক্ত করা এবং একে অপরের উপর রাখার জন্য কাঠামোগত নকশা তৈরি করা।

আপনি সি তে অবস্থিত ওওর পথে সত্যিই প্রচুর পরিমাণে এটি করতে পারেন, যদিও এটি বেশ কয়েকবার মনে হলেও ওও ধারণাগুলি মন থেকে সম্পূর্ণরূপে গঠিত হয়নি #include<favorite_OO_Guru.h>। তারা সত্যই সময়ের প্রতিষ্ঠিত সেরা অনুশীলনের অনেকগুলি গঠন করেছিল। ওও ভাষা এবং সিস্টেমগুলি কেবলমাত্র দিনের প্রোগ্রামিং জিটজিস্টের পাতিত এবং প্রসারিত অংশ।


4

প্রশ্নের উত্তরটি হ্যাঁ, আপনি পারবেন '।

অবজেক্ট-ওরিয়েন্টেড সি (ওওসি) কিটটি তাদের জন্য যাঁরা কোনও অবজেক্ট-ভিত্তিক পদ্ধতিতে প্রোগ্রাম করতে চান, তবে ভাল পুরানো সিটিতেও আঁটেন। ওওসি ক্লাস, একক এবং একাধিক উত্তরাধিকার, ব্যতিক্রম হ্যান্ডলিং প্রয়োগ করে।

বৈশিষ্ট্য

Only কেবল সি ম্যাক্রো এবং ফাংশন ব্যবহার করে, কোনও ভাষা এক্সটেনশন প্রয়োজন! (ANSI-সি)

Application আপনার অ্যাপ্লিকেশনটির জন্য সহজ-পাঠযোগ্য উত্স কোড। জিনিসগুলি যতটা সম্ভব সহজ করার জন্য যত্ন নেওয়া হয়েছিল।

ক্লাসের একক উত্তরাধিকার

Interface ইন্টারফেস এবং মিশ্রণগুলি দ্বারা একাধিক উত্তরাধিকার (সংস্করণ 1.3 থেকে)

Ex ব্যতিক্রমগুলি কার্যকর করা হচ্ছে (খাঁটি সিতে!)

ক্লাসের জন্য ভার্চুয়াল ফাংশন

Class সহজ শ্রেণীর প্রয়োগের জন্য বাহ্যিক সরঞ্জাম

আরও তথ্যের জন্য, 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

সুতরাং পরামর্শটি হ'ল খাঁটি সি স্টাইলকে আটকে রাখুন এবং জোর করে কোনও সি ++ স্টাইলে জোর করে দেখার চেষ্টা করবেন না। এছাড়াও এই উপায়টি নিজেকে একটি API তৈরির খুব পরিষ্কার উপায়ে ধার দেয়।


উত্তরাধিকারের জন্য সাধারণত বেস বর্গ বা উদাহরণ কাঠামো উত্পন্ন একটিতে এম্বেড করা হয়, আলাদাভাবে বরাদ্দ করা হয় না এবং পয়েন্টার ব্যবহার করে উল্লেখ করা হয়। এই ভাবে শীর্ষস্থানীয় বেসটি তার যে কোনও উত্পন্ন ধরণের কাঠামোর শুরুতে সর্বদা থাকে, তাই এগুলি একে অপরের কাছে সহজেই কাস্ট করা যেতে পারে, যা আপনি কোনও অফসেটে থাকা পয়েন্টারগুলি দিয়ে করতে পারবেন না।
আন্ডারস্কোর_১১

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% ক্ষেত্রে একক উত্তরাধিকারের প্রয়োজনগুলি আবরণ করে। এবং একক উত্তরাধিকার সহজ এবং কোনও মূল্য ব্যয় হয় না।

এছাড়াও আমি টাইপ সুরক্ষা সম্পর্কে যত্ন নেই। আমি মনে করি আপনাকে প্রোগ্রামিং ভুল থেকে রোধ করতে আপনার সংকলকের উপর নির্ভর করা উচিত নয়। এবং এটি আপনাকে কেবল ত্রুটির একটি ছোট অংশ থেকে youাল দেয় sh

সাধারণত কোনও অবজেক্ট ওরিয়েন্টেড পরিবেশে আপনি যথাসম্ভব মেমরি ম্যানেজমেন্টকে স্বয়ংক্রিয় করতে রেফারেন্স গণনা প্রয়োগ করতে চান। সুতরাং আমি "অবজেক্ট" মূল শ্রেণিতে একটি রেফারেন্স গণনাও রেখেছি এবং হিপ মেমরির বরাদ্দ এবং অবলম্বনকে encapsulate করতে কিছু কার্যকারিতা।

এটি সবই খুব সাধারণ এবং দুর্বল এবং সি ++ এর দানবটির সাথে মোকাবিলা করার জন্য আমাকে বাধ্য না করে আমাকে ওওর প্রয়োজনীয় জিনিসগুলি দেয়। এবং আমি সি ল্যান্ডে থাকার নমনীয়তা বজায় রেখেছি, যা অন্যান্য বিষয়ের মধ্যে তৃতীয় পক্ষের লাইব্রেরিগুলিকে সংহত করা সহজ করে তোলে।


1

আমি অবজেক্টিভ-সি ব্যবহার করার প্রস্তাব দিচ্ছি এটি সি এর সুপারস্টেট is

যদিও উদ্দেশ্য-সি 30 বছরের পুরানো, এটি মার্জিত কোড লেখার অনুমতি দেয়।

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



এটি কোনও উত্তর নয়। তবে যাইহোক, @YYYOYonnY: আমি অবজেক্টিভ-সি ব্যবহার করি না এবং সি ++ ব্যবহার করি না, তবে এর মতো মন্তব্যগুলি ভিত্তিহীন নয় এবং আপনি কোনও সরবরাহ করেন নি। আপনি কেন দাবি করেন যে অবজেক্টিভ-সি "আসলে অবজেক্ট অরিয়েন্টেড ..." হতে কম? এবং অবজেক্টিভ-সি ব্যর্থ হলে কেন সি ++ সফল হয়? মজার ব্যাপার যে উদ্দেশ্য সি, ভাল, আক্ষরিক শব্দ আছে অবজেক্ট তার নামে, যেহেতু সি ++ একটি মাল্টি-দৃষ্টান্ত ভাষা, কোনো গলি এক হিসাবে বাজারের নিজেই (অর্থাত না প্রাথমিকভাবে গলি, & কিছু বরং চরম লোক দৃষ্টিভঙ্গি নেই গলি মোটেও) ... তাই আপনি কি নিশ্চিত যে আপনি এই নামগুলি ভুল উপায়ে পাবেন নি?
আন্ডারস্কোর_

0

হ্যাঁ, তবে আমি কখনও কাউকে সি দিয়ে কোনও ধরণের বহুবর্ষ প্রয়োগ করার চেষ্টা করতে দেখিনি


6
আপনার আরও চারদিকে তাকাতে হবে :) উদাহরণস্বরূপ, মাইক্রোসফ্টের ডাইরেক্ট এক্সের একটি পলিমারফিক সি ইন্টারফেস রয়েছে।
এশেলি

8
উদাহরণস্বরূপ লিনাক্স কার্নেল প্রয়োগটি দেখুন। এটি সি তে খুব সাধারণ এবং বহুল ব্যবহৃত অনুশীলন
ইলিয়া


1
পলিমারফিজম সি তে বিরল নয়, অন্যদিকে একাধিক উত্তরাধিকার।
জোহান বিজেরেহল্ট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.