সি তে অবজেক্ট-ওরিয়েন্টেশন


157

নিফ্টি প্রিপ্রোসেসর হ্যাকগুলির একটি সেট (এএনএসআই সি 89 / আইএসও সি 90 সামঞ্জস্যপূর্ণ) যা সিতে কিছু ধরণের কুৎসিত (তবে ব্যবহারযোগ্য) অবজেক্ট-ওরিয়েন্টেশন সক্ষম করে?

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


এছাড়াও আপনি সিতে অবজেক্ট ওরিয়েন্টেড কোড লিখতে পারেন?


1
আমি ডি শিখতে সাড়া দিতে পারি এবং সি সামঞ্জস্যপূর্ণ অবি ব্যবহার করতে পারি যেখানে আপনার সত্যিকার অর্থে সি ডিজিটালমার্স
টিম ম্যাথিউজ

2
@ দিনাহ: "আরও দেখুন" এর জন্য আপনাকে ধন্যবাদ। পোস্টটি আকর্ষণীয় ছিল।

1
মজার প্রশ্নটি মনে হচ্ছে আপনি কেন সি ও ওপ-এর প্রি-প্রসেসর হ্যাক চান?
ক্যালিথ

3
@ ক্যালিথ: আমি দেখতে পেয়েছি যে ওওপি দরকারী এবং "আমি এমন কিছু এম্বেডেড সিস্টেমের সাথে কাজ করি যা কেবলমাত্র একটি সি সংকলক উপলব্ধ" (উপরে থেকে)। তদুপরি, আপনি কি নিফটি প্রিপ্রোসেসর হ্যাকগুলি আকর্ষণীয় দেখতে পান না?

উত্তর:


31

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

সি এর ব্যতিক্রম হ'ল অন্যান্য ওও ভাষায় পাওয়া TRY-CATCH-FinalLY এর C89 বাস্তবায়ন। এটি একটি পরীক্ষার এবং কিছু উদাহরণ সহ আসে।

উভয় লরেন্ট ডেনিয়াউ, যা সি- তে ওওপিতে প্রচুর কাজ করছে ।


@ ভনব্র্যান্ড সিওএস গিথুবতে স্থানান্তরিত হয়েছে যেখানে শেষ গ্রীষ্মের শেষ প্রতিশ্রুতি রয়েছে। পরিপক্কতা কমিটমেন্টের অভাবকে ব্যাখ্যা করতে পারে।
ফিলান্ট

185

আমি সি-সিনট্যাক্সটিকে আরও অন্য কোনও অবজেক্ট-ভিত্তিক ভাষার মতো তৈরি করার চেষ্টা করতে প্রিপ্রসেসর (আব) ব্যবহারের বিরুদ্ধে পরামর্শ দেব। সর্বাধিক প্রাথমিক স্তরে আপনি কেবল প্লেইন স্ট্রাক্টকে অবজেক্ট হিসাবে ব্যবহার করেন এবং এগুলি পয়েন্টার দিয়ে সরিয়ে দেন:

struct monkey
{
    float age;
    bool is_male;
    int happiness;
};

void monkey_dance(struct monkey *monkey)
{
    /* do a little dance */
}

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

struct base
{
    /* base class members */
};

struct derived
{
    struct base super;
    /* derived class members */
};

struct derived d;
struct base *base_ptr = (struct base *)&d;  // upcast
struct derived *derived_ptr = (struct derived *)base_ptr;  // downcast

পলিমারফিজম (অর্থাত্ ভার্চুয়াল ফাংশন) পেতে, আপনি ফাংশন পয়েন্টার এবং বিকল্পভাবে ফাংশন পয়েন্টার টেবিলগুলি ব্যবহার করেন যা ভার্চুয়াল টেবিল বা ভেটেবল হিসাবেও পরিচিত:

struct base;
struct base_vtable
{
    void (*dance)(struct base *);
    void (*jump)(struct base *, int how_high);
};

struct base
{
    struct base_vtable *vtable;
    /* base members */
};

void base_dance(struct base *b)
{
    b->vtable->dance(b);
}

void base_jump(struct base *b, int how_high)
{
    b->vtable->jump(b, how_high);
}

struct derived1
{
    struct base super;
    /* derived1 members */
};

void derived1_dance(struct derived1 *d)
{
    /* implementation of derived1's dance function */
}

void derived1_jump(struct derived1 *d, int how_high)
{
    /* implementation of derived 1's jump function */
}

/* global vtable for derived1 */
struct base_vtable derived1_vtable =
{
    &derived1_dance, /* you might get a warning here about incompatible pointer types */
    &derived1_jump   /* you can ignore it, or perform a cast to get rid of it */
};

void derived1_init(struct derived1 *d)
{
    d->super.vtable = &derived1_vtable;
    /* init base members d->super.foo */
    /* init derived1 members d->foo */
}

struct derived2
{
    struct base super;
    /* derived2 members */
};

void derived2_dance(struct derived2 *d)
{
    /* implementation of derived2's dance function */
}

void derived2_jump(struct derived2 *d, int how_high)
{
    /* implementation of derived2's jump function */
}

struct base_vtable derived2_vtable =
{
   &derived2_dance,
   &derived2_jump
};

void derived2_init(struct derived2 *d)
{
    d->super.vtable = &derived2_vtable;
    /* init base members d->super.foo */
    /* init derived1 members d->foo */
}

int main(void)
{
    /* OK!  We're done with our declarations, now we can finally do some
       polymorphism in C */
    struct derived1 d1;
    derived1_init(&d1);

    struct derived2 d2;
    derived2_init(&d2);

    struct base *b1_ptr = (struct base *)&d1;
    struct base *b2_ptr = (struct base *)&d2;

    base_dance(b1_ptr);  /* calls derived1_dance */
    base_dance(b2_ptr);  /* calls derived2_dance */

    base_jump(b1_ptr, 42);  /* calls derived1_jump */
    base_jump(b2_ptr, 42);  /* calls derived2_jump */

    return 0;
}

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

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


6
অ্যাডাম, এক ধরণের গ্লোবাল ভিটিবেল পরিবর্তন করার মজাদার হ'ল সি-তে হাঁস-টাইপিং অনুকরণ করা :)
jmucchiello

আমি এখন সি ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ অবশ্যই অবিরত সি ++ বাক্য গঠনটি আরও পরিষ্কার, আমি ভাবছি যদি সি ++ এবং সি এর মধ্যে কিছু হাইব্রিড অর্জন করা যায়, তবে অকার্যকর * এখনও বৈধ castালাইযোগ্য টাইপ হবে। এই অংশটি struct derived {struct base super;};অনুমান করে স্পষ্ট যে এটি কীভাবে কাজ করে, যেহেতু বাইটস ক্রম দ্বারা এটি সঠিক।
জোকুন

2
মার্জিত কোড জন্য +1, ভাল লেখা। আমি ঠিক এটিই খুঁজছিলাম!
হোমঙ্কুলাস রেটিকুলি

3
সাবাশ. ঠিক এটিই আমি এটি করছি এবং এটিও সঠিক উপায়। স্ট্রাক্ট / অবজেক্টকে মনে রেখে পয়েন্টারটির পরিবর্তে আপনার কেবলমাত্র একটি পূর্ণসংখ্যা (ঠিকানা) এ একটি পয়েন্টারটি পাস করা উচিত। এটি আপনাকে সীমাহীন পলিমারফিক পদ্ধতিতে কল করার জন্য যে কোনও ধরণের অবজেক্টে যেতে দেয়। এছাড়াও, কেবলমাত্র হারিয়ে যাওয়া জিনিস হ'ল আপনার স্ট্রাক্টগুলি (বস্তু / শ্রেণি) আরম্ভ করার জন্য একটি ফাংশন। এটিতে একটি ম্যালোক ফাংশন অন্তর্ভুক্ত হবে এবং একটি পয়েন্টার ফিরিয়ে দেবে। সম্ভবত আমি সি-তে মেসেজ পাসিং (উদ্দেশ্য-সি) কীভাবে করব তার একটি টুকরো যুক্ত করব

1
এটিই খড়টি আমাকে সি ++ বিভক্ত করে, এবং আরও সি ​​ব্যবহার করতে (আমি কেবল উত্তরাধিকারের জন্য সি ++ ব্যবহার করার আগে) আপনাকে ধন্যবাদ
অ্যান কুইন

31

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

  • প্রতিটি বস্তুর নিজস্ব ফাইল ছিল
  • সর্বজনীন ফাংশন এবং ভেরিয়েবলগুলি কোনও বস্তুর জন্য .h ফাইলে সংজ্ঞায়িত করা হয়
  • ব্যক্তিগত ভেরিয়েবল এবং ফাংশনগুলি কেবলমাত্র .c ফাইলটিতে অবস্থিত
  • "উত্তরাধিকারী" হতে স্ট্রাক্টের প্রথম সদস্যকে উত্তরাধিকারী হওয়ার উদ্দেশ্যে তৈরি করে একটি নতুন স্ট্রাক্ট তৈরি করা হয়

উত্তরাধিকার বর্ণনা করা কঠিন, তবে মূলত এটি ছিল:

struct vehicle {
   int power;
   int weight;
}

তারপরে অন্য ফাইলে:

struct van {
   struct vehicle base;
   int cubic_size;
}

তারপরে আপনি মেমরিতে একটি ভ্যান তৈরি করতে এবং কোড দ্বারা ব্যবহার করা যা কেবল যানবাহন সম্পর্কে জানত:

struct van my_van;
struct vehicle *something = &my_van;
vehicle_function( something );

এটি খুব সুন্দরভাবে কাজ করেছে এবং .h ফাইলগুলি প্রতিটি বস্তুর সাথে আপনার কী করতে সক্ষম হবেন ঠিক তা সংজ্ঞায়িত করে।


"অবজেক্ট" এর অভ্যন্তরীণ সমস্তগুলি প্রকাশ্য ব্যতীত আমি এই সমাধানটি সত্যিই পছন্দ করি।
লরেন্স ডল

6
@ সফটওয়্যার বানর: সি এর অ্যাক্সেস নিয়ন্ত্রণ নেই। বাস্তবায়নের বিশদটি গোপন করার একমাত্র উপায় হল অস্বচ্ছ পয়েন্টারগুলির মাধ্যমে ইন্টারঅ্যাক্ট করা, যা বেশ বেদনাদায়ক হয়ে উঠতে পারে, যেহেতু সমস্ত ক্ষেত্রটি অ্যাক্সেসর পদ্ধতির মাধ্যমে অ্যাক্সেস করা প্রয়োজন যা সম্ভবত ইনলাইন করা যায় না।
অ্যাডাম রোজেনফিল্ড

1
@ অ্যাডাম: লিঙ্ক-টাইম অপ্টিমাইজেশান সমর্থনকারী সংকলকরা এগুলিকে ঠিকঠাক ইনলাইন করবে ...
ক্রিস্টোফ

9
আপনি যদি এটি করেন তবে আপনার এটিও নিশ্চিত করতে হবে যে .c ফাইলের সমস্ত ফাংশন যা জনসাধারণ হিসাবে সংজ্ঞায়িত হয় না তা স্থির হিসাবে সংজ্ঞায়িত করা হয় যাতে তারা আপনার অবজেক্ট ফাইলগুলিতে নামযুক্ত ফাংশন হিসাবে শেষ না হয়। এটি নিশ্চিত করে যে লিঙ্ক পর্বে কেউ তাদের নাম খুঁজে না পাবে।
jmucchiello

2
@ মার্সেল: সি ব্যবহৃত হয়েছিল কারণ স্বায়ত্তশাসিত সিস্টেমগুলির জন্য বিভিন্ন প্রসেসর চালিত নিম্ন স্তরের বোর্ডগুলিতে কোড মোতায়েন করা হয়েছিল। তারা সকলেই সি থেকে স্ব স্ব দেশীয় বাইনারিগুলিতে সংকলন সমর্থন করেছিল। আপনি যখন তারা কী চেষ্টা করছেন তা বুঝতে পেরে এই পদ্ধতির কোডটি খুব সহজেই পড়তে পারা যায়।
কিভেলি

18

লিনাক্সের জন্য জিনোম ডেস্কটপটি অবজেক্ট-ওরিয়েন্টেড সি-তে লেখা রয়েছে এবং এতে " জিওজেক্ট " নামে একটি অবজেক্ট মডেল রয়েছে যা বৈশিষ্ট্য, উত্তরাধিকার, পলিমারফিজম, পাশাপাশি রেফারেন্স, ইভেন্ট হ্যান্ডলিং ("সংকেত" বলা হয়), রানটাইম সমর্থন করে টাইপিং, ব্যক্তিগত ডেটা, ইত্যাদি

এর মধ্যে ক্লাসের শ্রেণিবিন্যাসের চারপাশে টাইপস্টাস্টিং ইত্যাদির মতো প্রিপ্রোসেসর হ্যাক রয়েছে Here

শ্রেণীর উত্স

ক্লাস শিরোনাম

জিওজেক্ট স্ট্রাকচারের অভ্যন্তরে একটি জিটিপাইজ পূর্ণসংখ্যা রয়েছে যা জিএলিবের ডায়নামিক টাইপিং সিস্টেমের জন্য যাদু নম্বর হিসাবে ব্যবহৃত হয় (এটির সন্ধানের জন্য আপনি পুরো কাঠামোটিকে "জিটিপাইপ" এ কাস্ট করতে পারেন)।


দুর্ভাগ্যক্রমে, রিড মি / টিউটোরিয়াল ফাইল (উইকি লিঙ্ক) কাজ করছে না এবং এর জন্য কেবল রেফারেন্স ম্যানুয়াল রয়েছে (আমি জিওজেক্ট সম্পর্কে বলছি এবং জিটিকে নয়)। দয়া করে এর জন্য কয়েকটি টিউটোরিয়াল ফাইল সরবরাহ করুন ...
FL4SOF

লিঙ্কগুলি স্থির করা হয়েছে।
জেমস কেপ

4
লিঙ্কগুলি আবার ভেঙে গেছে।
সানরেমে

6

আমি সি-তে এই জাতীয় জিনিসটি করতাম, ওওপ কী তা জানার আগে।

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

ধারণাটি হ'ল অবজেক্টটি xxx_crt () ব্যবহার করে তাত্ক্ষণিকভাবে xX_dlt () ব্যবহার করে মুছে ফেলা হয়। প্রতিটি "সদস্য" পদ্ধতি চালানোর জন্য একটি বিশেষভাবে টাইপ করা পয়েন্টার নেয়।

আমি এই পদ্ধতিতে একটি লিঙ্কযুক্ত তালিকা, চক্রীয় বাফার এবং অন্যান্য অনেকগুলি জিনিস কার্যকর করেছি।

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

dtb.c:

#include <limits.h>
#include <string.h>
#include <stdlib.h>

static void dtb_xlt(void *dst, const void *src, vint len, const byte *tbl);

DTABUF *dtb_crt(vint minsiz,vint incsiz,vint maxsiz) {
    DTABUF          *dbp;

    if(!minsiz) { return NULL; }
    if(!incsiz)                  { incsiz=minsiz;        }
    if(!maxsiz || maxsiz<minsiz) { maxsiz=minsiz;        }
    if(minsiz+incsiz>maxsiz)     { incsiz=maxsiz-minsiz; }
    if((dbp=(DTABUF*)malloc(sizeof(*dbp))) == NULL) { return NULL; }
    memset(dbp,0,sizeof(*dbp));
    dbp->min=minsiz;
    dbp->inc=incsiz;
    dbp->max=maxsiz;
    dbp->siz=minsiz;
    dbp->cur=0;
    if((dbp->dta=(byte*)malloc((vuns)minsiz)) == NULL) { free(dbp); return NULL; }
    return dbp;
    }

DTABUF *dtb_dlt(DTABUF *dbp) {
    if(dbp) {
        free(dbp->dta);
        free(dbp);
        }
    return NULL;
    }

vint dtb_adddta(DTABUF *dbp,const byte *xlt256,const void *dtaptr,vint dtalen) {
    if(!dbp) { errno=EINVAL; return -1; }
    if(dtalen==-1) { dtalen=(vint)strlen((byte*)dtaptr); }
    if((dbp->cur + dtalen) > dbp->siz) {
        void        *newdta;
        vint        newsiz;

        if((dbp->siz+dbp->inc)>=(dbp->cur+dtalen)) { newsiz=dbp->siz+dbp->inc; }
        else                                       { newsiz=dbp->cur+dtalen;   }
        if(newsiz>dbp->max) { errno=ETRUNC; return -1; }
        if((newdta=realloc(dbp->dta,(vuns)newsiz))==NULL) { return -1; }
        dbp->dta=newdta; dbp->siz=newsiz;
        }
    if(dtalen) {
        if(xlt256) { dtb_xlt(((byte*)dbp->dta+dbp->cur),dtaptr,dtalen,xlt256); }
        else       { memcpy(((byte*)dbp->dta+dbp->cur),dtaptr,(vuns)dtalen);   }
        dbp->cur+=dtalen;
        }
    return 0;
    }

static void dtb_xlt(void *dst,const void *src,vint len,const byte *tbl) {
    byte            *sp,*dp;

    for(sp=(byte*)src,dp=(byte*)dst; len; len--,sp++,dp++) { *dp=tbl[*sp]; }
    }

vint dtb_addtxt(DTABUF *dbp,const byte *xlt256,const byte *format,...) {
    byte            textÝ501¨;
    va_list         ap;
    vint            len;

    va_start(ap,format); len=sprintf_len(format,ap)-1; va_end(ap);
    if(len<0 || len>=sizeof(text)) { sprintf_safe(text,sizeof(text),"STRTOOLNG: %s",format); len=(int)strlen(text); }
    else                           { va_start(ap,format); vsprintf(text,format,ap); va_end(ap);                     }
    return dtb_adddta(dbp,xlt256,text,len);
    }

vint dtb_rmvdta(DTABUF *dbp,vint len) {
    if(!dbp) { errno=EINVAL; return -1; }
    if(len > dbp->cur) { len=dbp->cur; }
    dbp->cur-=len;
    return 0;
    }

vint dtb_reset(DTABUF *dbp) {
    if(!dbp) { errno=EINVAL; return -1; }
    dbp->cur=0;
    if(dbp->siz > dbp->min) {
        byte *newdta;
        if((newdta=(byte*)realloc(dbp->dta,(vuns)dbp->min))==NULL) {
            free(dbp->dta); dbp->dta=null; dbp->siz=0;
            return -1;
            }
        dbp->dta=newdta; dbp->siz=dbp->min;
        }
    return 0;
    }

void *dtb_elmptr(DTABUF *dbp,vint elmidx,vint elmlen) {
    if(!elmlen || (elmidx*elmlen)>=dbp->cur) { return NULL; }
    return ((byte*)dbp->dta+(elmidx*elmlen));
    }

dtb.h

typedef _Packed struct {
    vint            min;                /* initial size                       */
    vint            inc;                /* increment size                     */
    vint            max;                /* maximum size                       */
    vint            siz;                /* current size                       */
    vint            cur;                /* current data length                */
    void            *dta;               /* data pointer                       */
    } DTABUF;

#define dtb_dtaptr(mDBP)                (mDBP->dta)
#define dtb_dtalen(mDBP)                (mDBP->cur)

DTABUF              *dtb_crt(vint minsiz,vint incsiz,vint maxsiz);
DTABUF              *dtb_dlt(DTABUF *dbp);
vint                dtb_adddta(DTABUF *dbp,const byte *xlt256,const void *dtaptr,vint dtalen);
vint                dtb_addtxt(DTABUF *dbp,const byte *xlt256,const byte *format,...);
vint                dtb_rmvdta(DTABUF *dbp,vint len);
vint                dtb_reset(DTABUF *dbp);
void                *dtb_elmptr(DTABUF *dbp,vint elmidx,vint elmlen);

পিএস: ভিন্টটি কেবল ইনট টাইপফ ছিল - আমি এটির স্মরণ করিয়ে দিতে এটি ব্যবহার করেছি যে এটির দৈর্ঘ্য প্ল্যাটফর্ম থেকে প্ল্যাটফর্মের (পোর্টিংয়ের জন্য) পরিবর্তনশীল ছিল।


7
পবিত্র মোলি, এটি একটি অস্পষ্ট সি প্রতিযোগিতা জিততে পারে! আমি এটা পছন্দ করি! :)
ঘোড়াচুরি

পছন্দ করেছেন এটি প্রকাশিত হয়েছে। এছাড়াও তারা আইকোক্যাসাইজ সরঞ্জামটির বিপরীতে হেডার ফাইলগুলির অপব্যবহারের অন্তর্ভুক্তি বিবেচনা করে। এটিও সম্পূর্ণ প্রোগ্রাম নয়। ২০০৯ এর কোনও প্রতিযোগিতা ছিল না তাই আইওকসিএসকে তুলনা করতে পারবেন না। সিপিপি অনেকবার গালাগাল করা হয়েছে তাই এটি বেশ পুরানো। ইত্যাদি। আমি নেতিবাচক হওয়ার চেষ্টা করছি না তবে আমি বাস্তববাদী। আমি আপনার অর্থটি বাছাই করি যদিও এটি ভাল পড়ে এবং আমি এটির উপরে ভোট দিয়েছি। (এবং হ্যাঁ আমি এতে অংশ নিয়েছি এবং হ্যাঁ আমিও জিতেছি))
প্রাইফটান

6

সামান্য সামান্য অফ-টপিক, তবে আসল সি ++ সংকলক, সিফ্রন্ট , সি ++ সি থেকে সিলেক্ট করে এসেম্বলারের জন্য।

এখানে সংরক্ষিত ।


আমি আসলে এটি আগে দেখেছি। আমি বিশ্বাস করি এটি একটি দুর্দান্ত কাজ ছিল।

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

5

যদি আপনি স্থিতিশীল পদ্ধতি হিসাবে অবজেক্টগুলিতে আহ্বান করা পদ্ধতিগুলি সম্পর্কে মনে করেন যা কোনও thisকার্যকে একটি অন্তর্নিহিত ' ' পাস করে তবে এটি সি এর ওও চিন্তাভাবনাকে সহজ করে তুলতে পারে।

উদাহরণ স্বরূপ:

String s = "hi";
System.out.println(s.length());

হয়ে:

string s = "hi";
printf(length(s)); // pass in s, as an implicit this

বা এমন কিছু।


6
@ আর্টেলিয়াস: অবশ্যই, তবে এটি বর্ণিত না হওয়া পর্যন্ত কখনও কখনও সুস্পষ্ট হয় না। এই জন্য +1।
লরেন্স ডল

1
আরও ভাল হবেstring->length(s);
ওজেজমিস্টার

4

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


আমি এতে কোনও ফ্যাক্টরি ফাংশন দেখতে পাচ্ছি না (ffmpeg), বরং এটি বহুবর্ষ / উত্তরাধিকার (উপরে বর্ণিত তুচ্ছ উপায়) ব্যবহার করছে বলে মনে হচ্ছে না।
এফএল

avcodec_open একটি কারখানা ফাংশন। এটি ফাংশন পয়েন্টারগুলিকে একটি AVCodecContext স্ট্রাক্টে (যেমন ড্র_হরিজ_ব্যান্ডের মতো) স্টাফ করে। আপনি যদি অ্যাভোডেক.এসএ এফএফ_সিএমএমএন_ফ্রেমে ম্যাক্রোর ব্যবহারের দিকে লক্ষ্য করেন তবে আপনি ডেটা সদস্যদের উত্তরাধিকারের মতো কিছু দেখতে পাবেন। আইএমএইচও, ffmpeg আমাকে প্রমাণ করে যে ওওপি সবচেয়ে ভাল সি ++ এ করা হয়, সি না
মিঃ ফুজ

3

আপনি কি সত্যিই catefully মনে পারেন, এমনকি প্রমিত C লাইব্রেরি ব্যবহার গলি - বিবেচনা FILE *একটি উদাহরণ হিসাবে: fopen()একটি সূচনা FILE *বস্তু, এবং আপনি এটি সদস্য পদ্ধতি ব্যবহার ব্যবহার fscanf(), fprintf(), fread(), fwrite()এবং অন্যদের, এবং শেষ পর্যন্ত তা চূড়ান্ত fclose()

আপনি ছদ্ম-উদ্দেশ্য-সি পথে যেতে পারেন যা ততটা কঠিন নয়:

typedef void *Class;

typedef struct __class_Foo
{
    Class isa;
    int ivar;
} Foo;

typedef struct __meta_Foo
{
    Foo *(*alloc)(void);
    Foo *(*init)(Foo *self);
    int (*ivar)(Foo *self);
    void (*setIvar)(Foo *self);
} meta_Foo;

meta_Foo *class_Foo;

void __meta_Foo_init(void) __attribute__((constructor));
void __meta_Foo_init(void)
{
    class_Foo = malloc(sizeof(meta_Foo));
    if (class_Foo)
    {
        class_Foo = {__imp_Foo_alloc, __imp_Foo_init, __imp_Foo_ivar, __imp_Foo_setIvar};
    }
}

Foo *__imp_Foo_alloc(void)
{
    Foo *foo = malloc(sizeof(Foo));
    if (foo)
    {
        memset(foo, 0, sizeof(Foo));
        foo->isa = class_Foo;
    }
    return foo;
}

Foo *__imp_Foo_init(Foo *self)
{
    if (self)
    {
        self->ivar = 42;
    }
    return self;
}
// ...

ব্যবহার করা:

int main(void)
{
    Foo *foo = (class_Foo->init)((class_Foo->alloc)());
    printf("%d\n", (foo->isa->ivar)(foo)); // 42
    foo->isa->setIvar(foo, 60);
    printf("%d\n", (foo->isa->ivar)(foo)); // 60
    free(foo);
}

কোনও সুন্দর-পুরাতন অবজেক্টিভ-সি-টু-সি অনুবাদক ব্যবহার করা হলে এটি এই জাতীয় কিছু উদ্দেশ্য-সি কোড থেকে ফলাফল হতে পারে:

@interface Foo : NSObject
{
    int ivar;
}
- (int)ivar;
- (void)setIvar:(int)ivar;
@end

@implementation Foo
- (id)init
{
    if (self = [super init])
    {
        ivar = 42;
    }
    return self;
}
@end

int main(void)
{
    Foo *foo = [[Foo alloc] init];
    printf("%d\n", [foo ivar]);
    [foo setIvar:60];
    printf("%d\n", [foo ivar]);
    [foo release];
}

কী __attribute__((constructor))না void __meta_Foo_init(void) __attribute__((constructor))?
এই ড্রু

1
এটি একটি জিসিসি এক্সটেনশন যা বাইনারি মেমরিতে লোড হওয়ার পরে চিহ্নিত ফাংশনটি কল হবে কিনা তা নিশ্চিত করবে। @ এড্রু
ম্যাক্সথন চ্যান

popen(3)একটি ফেরৎ FILE *অন্য একটি উদাহরণ জন্য।
প্রাইফটান

3

আমি মনে করি অ্যাডাম রোজেনফিল্ড যা পোস্ট করেছেন তা হ'ল সি-তে ওওপি করার সঠিক উপায় I'd অন্য কথায় প্রকৃত বাস্তবায়ন .cফাইলে রাখা হবে, যখন ইন্টারফেসটি শিরোলেখ .hফাইলটিতে রাখা হবে। উদাহরণস্বরূপ, উপরের বানরের উদাহরণ ব্যবহার করে:

ইন্টারফেসটি দেখতে হবে:

//monkey.h

    struct _monkey;

    typedef struct _monkey monkey;

    //memory management
    monkey * monkey_new();
    int monkey_delete(monkey *thisobj);
    //methods
    void monkey_dance(monkey *thisobj);

আপনি .hকেবলমাত্র প্রোটোটাইপগুলি সংজ্ঞায়িত করছেন ইন্টারফেস ফাইলটিতে দেখতে পাবেন । তারপরে আপনি বাস্তবায়ন অংশ " .cফাইল" একটি স্ট্যাটিক বা গতিশীল লাইব্রেরিতে সংকলন করতে পারেন । এটি এনক্যাপসুলেশন তৈরি করে এবং আপনি ইচ্ছায় বাস্তবায়ন পরিবর্তন করতে পারেন। আপনার অবজেক্টের ব্যবহারকারীর এটির বাস্তবায়ন সম্পর্কে প্রায় কিছুই জানতে হবে। এটি অবজেক্টের সামগ্রিক ডিজাইনের দিকেও মনোযোগ দেয়।

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


আপনি typedef struct Monkey {} Monkey; টাইপডেফ তৈরি করার পরে এটি তৈরির পরে কীসের সাথে একটি কাঠামো ঘোষণা করতে পারেন ?
মার্কাসজে

1
@ মার্কাসজে struct _monkeyএটি কেবল একটি প্রোটোটাইপ। বাস্তব টাইপ সংজ্ঞাটি বাস্তবায়ন ফাইলে (.c ফাইল) সংজ্ঞায়িত করা হয়। এটি এনক্যাপসুলেশন প্রভাব তৈরি করে এবং এপিআই বিকাশকারীকে এপিআই পরিবর্তন না করে ভবিষ্যতে বানরের কাঠামোর নতুন সংজ্ঞা দিতে দেয়। API- র ব্যবহারকারীদের কেবল আসল পদ্ধতিগুলির সাথেই উদ্বিগ্ন হওয়া দরকার। কীভাবে অবজেক্ট / স্ট্রাক্ট নির্ধারণ করা হয় সেগুলি সহ এপিআই ডিজাইনার বাস্তবায়নের যত্ন নেয়। সুতরাং অবজেক্ট / স্ট্রাক্টের বিবরণগুলি ব্যবহারকারী (একটি অস্বচ্ছ ধরণের) থেকে লুকানো আছে।

আমি শিরোনামগুলিতে আমার স্ট্রাক্ট সংজ্ঞায়িত করি, এটি কি আদর্শ নয়? ঠিক আছে, আমি এটি সেভাবে করি কারণ আমার মাঝে মাঝে library লাইব্রেরির বাইরে কাঠামোর সদস্যদের অ্যাক্সেস করা প্রয়োজন।
মারকাসজে

1
@ মার্কাসজে আপনি ইচ্ছে করলে শিরোনামগুলিতে আপনার স্ট্রাক্ট সংজ্ঞায়িত করতে পারেন (কোনও মান নেই)। তবে আপনি যদি রাস্তার নীচে এর অভ্যন্তরীণ কাঠামো পরিবর্তন করতে চান তবে আপনি আপনার কোডটি ভেঙে দিতে পারেন। এনক্যাপসুলেশন কেবল কোডিংয়ের একটি স্টাইল যা আপনার কোডটি ভঙ্গ না করে বাস্তবায়ন পরিবর্তন করা সহজ করে তোলে। আপনি int getCount(ObjectType obj)যদি প্রয়োগের ফাইলে কাঠামোটি সংজ্ঞায়িত করতে চান তবে আপনি সর্বদা অ্যাক্সেসর পদ্ধতির মাধ্যমে আপনার সদস্যদের অ্যাক্সেস করতে পারেন ।

2

আমার সুপারিশ: সহজ রাখুন। আমার কাছে সবচেয়ে বড় সমস্যাটি হ'ল পুরানো সফ্টওয়্যার (কখনও কখনও 10 বছরেরও বেশি পুরানো) বজায় রাখা। কোডটি যদি সহজ না হয় তবে এটি কঠিন হতে পারে। হ্যাঁ, সি-তে পলিমারফিজম সহ একটি খুব দরকারী ওওপি লিখতে পারে তবে এটি পড়া কঠিন হতে পারে।

আমি সাধারণ বস্তুগুলিকে পছন্দ করি যা কিছু সু-সংজ্ঞায়িত কার্যকারিতা encapsulate করে। এর একটি দুর্দান্ত উদাহরণ হ'ল জিলিবি 2 , উদাহরণস্বরূপ একটি হ্যাশ টেবিল:

GHastTable* my_hash = g_hash_table_new(g_str_hash, g_str_equal);
int size = g_hash_table_size(my_hash);
...

g_hash_table_remove(my_hash, some_key);

কীগুলি হ'ল:

  1. সাধারণ স্থাপত্য এবং নকশার প্যাটার্ন pattern
  2. বেসিক ওওপি এনক্যাপসুলেশন অর্জন করে।
  3. কার্যকর করা, পড়া, বোঝার এবং বজায় রাখা সহজ

1

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

সি এর ওওপিতে আসল সমস্যাটি হ'ল যখন ভেরিয়েবলগুলি প্রস্থান করার সুযোগ পায়। কোনও সংকলক উত্পাদিত ধ্বংসকারী নেই এবং এটি সমস্যার কারণ হতে পারে। ম্যাক্রোগগুলি সম্ভবত সহায়তা করতে পারে তবে এটি সর্বদা দেখতে কুৎসিত হতে চলেছে।


1
সি তে প্রোগ্রামিং করার সময় আমি ifবিবৃতি ব্যবহার করে এবং শেষে এগুলি প্রকাশ করে সুযোগটি মোকাবিলা করি । উদাহরণস্বরূপif ( (obj = new_myObject()) ) { /* code using myObject */ free_myObject(obj); }

1

সি এর সাথে অবজেক্ট ওরিয়েন্টেড স্টাইলে প্রোগ্রাম করার আরেকটি উপায় হ'ল একটি কোড জেনারেটর ব্যবহার করা যা কোনও ডোমেন নির্দিষ্ট ভাষা সি-তে রূপান্তর করে As


0
#include "triangle.h"
#include "rectangle.h"
#include "polygon.h"

#include <stdio.h>

int main()
{
    Triangle tr1= CTriangle->new();
    Rectangle rc1= CRectangle->new();

    tr1->width= rc1->width= 3.2;
    tr1->height= rc1->height= 4.1;

    CPolygon->printArea((Polygon)tr1);

    printf("\n");

    CPolygon->printArea((Polygon)rc1);
}

আউটপুট:

6.56
13.12

সি এর সাথে ওও প্রোগ্রামিং কী তা একটি শো এখানে দেওয়া হয়েছে

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

CPolygon তাত্ক্ষণিকভাবে তৈরি হয় না কারণ আমরা এটি কেবল আনন্দেরিট্যান্স শৃঙ্খলের নিখরচায় বস্তুগুলি যাতে সাধারণ দিকগুলি রয়েছে তবে সেগুলির বিভিন্ন প্রয়োগ (পলিমারফিজম) ব্যবহার করতে ব্যবহার করি।


0

সিডির মাধ্যমে ওওপি কীভাবে অর্জন করবেন তার @ অ্যাডাম রোজেনফিল্ডের খুব ভাল ব্যাখ্যা রয়েছে

পাশাপাশি, আমি আপনাকে পড়ার জন্য সুপারিশ করব recommend

1) pjsip

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

2) আইওএস রানটাইম

আইওএস রানটাইম কীভাবে উদ্দেশ্য সিটিকে ক্ষমতা দেয় তা শিখুন এটি ইসা পয়েন্টার, মেটা ক্লাসের মাধ্যমে ওওপি অর্জন করে


0

আমার জন্য সিতে অবজেক্ট ওরিয়েন্টেশনটিতে এই বৈশিষ্ট্যগুলি থাকা উচিত:

  1. এনক্যাপসুলেশন এবং ডেটা লুকানো (স্ট্র্টগুলি / অস্বচ্ছ পয়েন্টার ব্যবহার করে অর্জন করা যেতে পারে)

  2. পলিমারফিজমের জন্য উত্তরাধিকার এবং সমর্থন (স্ট্রাক্ট ব্যবহার করে একক উত্তরাধিকার অর্জন করা যেতে পারে - নিশ্চিত করুন যে বিমূর্ত বেসটি তাত্পর্যযোগ্য নয়)

  3. কনস্ট্রাক্টর এবং ডেস্ট্রাক্টর কার্যকারিতা (অর্জন করা সহজ নয়)

  4. টাইপ চেকিং (কমপক্ষে ব্যবহারকারী-সংজ্ঞায়িত প্রকারের জন্য সি কোনও প্রয়োগ করে না)

  5. রেফারেন্স গণনা (বা আরআইআই বাস্তবায়নের জন্য কিছু )

  6. ব্যতিক্রম হ্যান্ডলিংয়ের জন্য সীমাবদ্ধ সমর্থন (সেটজ্যাম্প এবং লংজ্যাম্প)

উপরের উপরে এটি এএনএসআই / আইএসও নির্দিষ্টকরণের উপর নির্ভর করবে এবং সংকলক-নির্দিষ্ট কার্যকারিতার উপর নির্ভর করবে না।


সংখ্যার জন্য (5) - আপনি ডেস্ট্র্যাক্টর ছাড়া কোনও ভাষায় আরআইআই প্রয়োগ করতে পারবেন না (যার অর্থ RAII সি বা জাভাতে সংকলক-সমর্থিত কৌশল নয়)।
টম

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

সি ধ্বংসকারীদের সমর্থন করে না। এগুলি কাজ করার জন্য আপনাকে কিছু টাইপ করতে হবে। তার মানে তারা নিজেরাই পরিষ্কার করে না। জিওজেক্ট ভাষা পরিবর্তন করে না।
টম

0

http://ldeniau.web.cern.ch/ldeniau/html/oopc/oopc.html । যদি ডকুমেন্টেশনের মাধ্যমে অন্য কিছু না পড়া হয় তবে একটি আলোকিত অভিজ্ঞতা।


3
আপনি যে লিঙ্কটি ভাগ করছেন তার জন্য প্রসঙ্গটি সরবরাহ করুন। যদিও আপনি ভাগ করেছেন সেই লিঙ্কটি সত্যই খুব সহায়ক হতে পারে, তবে বরং প্রশ্নের উত্তর দেওয়া ভাগ করা নিবন্ধের মূল দিকগুলি ক্যাপচার করার পরামর্শ দেওয়া হচ্ছে। এইভাবে, লিঙ্কটি সরানো হলেও আপনার উত্তরটি এখনও প্রাসঙ্গিক এবং সহায়ক হবে।
ishmaelMakitla

0

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

/*
 * OOP in C
 *
 * gcc -o oop oop.c
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

struct obj2d {
    float x;                            // object center x
    float y;                            // object center y
    float (* area)(void *);
};

#define X(obj)          (obj)->b1.x
#define Y(obj)          (obj)->b1.y
#define AREA(obj)       (obj)->b1.area(obj)

void *
_new_obj2d(int size, void * areafn)
{
    struct obj2d * x = calloc(1, size);
    x->area = areafn;
    // obj2d constructor code ...
    return x;
}

// --------------------------------------------------------

struct rectangle {
    struct obj2d b1;        // base class
    float width;
    float height;
    float rotation;
};

#define WIDTH(obj)      (obj)->width
#define HEIGHT(obj)     (obj)->height

float rectangle_area(struct rectangle * self)
{
    return self->width * self->height;
}

#define NEW_rectangle()  _new_obj2d(sizeof(struct rectangle), rectangle_area)

// --------------------------------------------------------

struct triangle {
    struct obj2d b1;
    // deliberately unfinished to test error messages
};

#define NEW_triangle()  _new_obj2d(sizeof(struct triangle), triangle_area)

// --------------------------------------------------------

struct circle {
    struct obj2d b1;
    float radius;
};

#define RADIUS(obj)     (obj)->radius

float circle_area(struct circle * self)
{
    return M_PI * self->radius * self->radius;
}

#define NEW_circle()     _new_obj2d(sizeof(struct circle), circle_area)

// --------------------------------------------------------

#define NEW(objname)            (struct objname *) NEW_##objname()


int
main(int ac, char * av[])
{
    struct rectangle * obj1 = NEW(rectangle);
    struct circle    * obj2 = NEW(circle);

    X(obj1) = 1;
    Y(obj1) = 1;

    // your decision as to which of these is clearer, but note above that
    // macros also hide the fact that a member is in the base class

    WIDTH(obj1)  = 2;
    obj1->height = 3;

    printf("obj1 position (%f,%f) area %f\n", X(obj1), Y(obj1), AREA(obj1));

    X(obj2) = 10;
    Y(obj2) = 10;
    RADIUS(obj2) = 1.5;
    printf("obj2 position (%f,%f) area %f\n", X(obj2), Y(obj2), AREA(obj2));

    // WIDTH(obj2)  = 2;                                // error: struct circle has no member named width
    // struct triangle  * obj3 = NEW(triangle);         // error: triangle_area undefined
}

আমি মনে করি এটির একটি ভাল ভারসাম্য রয়েছে এবং সম্ভাব্য কিছু ভুলের জন্য এটি ত্রুটিগুলি তৈরি করে (কমপক্ষে ডিফল্ট জিসিসি 6.3 বিকল্পের সাহায্যে) বিভ্রান্তির পরিবর্তে সহায়ক। পুরো পয়েন্টটি কোন প্রোগ্রামার উত্পাদনশীলতার উন্নতি করতে হবে?


0

আপনার যদি একটু কোড লেখার দরকার হয় তবে এটি ব্যবহার করে দেখুন: https://github.com/fulminati/class-framework

#include "class-framework.h"

CLASS (People) {
    int age;
};

int main()
{
    People *p = NEW (People);

    p->age = 10;

    printf("%d\n", p->age);
}

2
দয়া করে উত্তর হিসাবে কোনও সরঞ্জাম বা লাইব্রেরি পোস্ট করবেন না। কমপক্ষে প্রদর্শিত হবে যে কীভাবে এটি উত্তরে নিজেই সমস্যাটি সমাধান করে।
বাউম মিট অজেন

0

আমি ম্যাক্রো সমাধানের ভিত্তিতে এটি নিয়েও কাজ করছি। সুতরাং এটি কেবলমাত্র ব্রেভেটের জন্য, আমি অনুমান করি ;-) তবে এটি ইতিমধ্যে বেশ সুন্দর এবং আমি ইতিমধ্যে এর উপরে কয়েকটি প্রকল্পে কাজ করছি। এটি এমনভাবে কাজ করে যাতে আপনি প্রথমে প্রতিটি শ্রেণীর জন্য একটি পৃথক শিরোনাম ফাইলটি সংজ্ঞায়িত করেন। এটার মত:

#define CLASS Point
#define BUILD_JSON

#define Point__define                            \
    METHOD(Point,public,int,move_up,(int steps)) \
    METHOD(Point,public,void,draw)               \
                                                 \
    VAR(read,int,x,JSON(json_int))               \
    VAR(read,int,y,JSON(json_int))               \

শ্রেণিটি বাস্তবায়নের জন্য, আপনি এর জন্য একটি শিরোনাম ফাইল এবং একটি সি ফাইল তৈরি করেন যেখানে আপনি পদ্ধতিগুলি প্রয়োগ করেন:

METHOD(Point,public,void,draw)
{
    printf("point at %d,%d\n", self->x, self->y);
}

আপনি ক্লাসটির জন্য তৈরি শিরোনামে, আপনার প্রয়োজনীয় অন্যান্য শিরোনাম অন্তর্ভুক্ত করুন এবং শ্রেণীর সাথে সম্পর্কিত ধরণের সংজ্ঞা দিন। উভয় শ্রেণির শিরোনাম এবং সি ফাইলটিতে আপনি শ্রেণীর স্পেসিফিকেশন ফাইল (প্রথম কোড উদাহরণ দেখুন) এবং একটি এক্স-ম্যাক্রো অন্তর্ভুক্ত করেন c এই এক্স-ম্যাক্রোস ( 1 , 2 , 3 ইত্যাদি) কোডটি প্রকৃত শ্রেণির কাঠামো এবং অন্যান্য ঘোষণায় প্রসারিত করবে।

একটি বর্গ উত্তরাধিকারী, #define SUPER supernameএবং যোগ করতেsupername__define \ হওয়া এবং শ্রেণীর সংজ্ঞায় প্রথম লাইন হিসাবে করা। দু'জনকেই সেখানে থাকতে হবে। এছাড়াও রয়েছে জেএসএন সমর্থন, সংকেত, বিমূর্ত শ্রেণি ইত্যাদি

একটি অবজেক্ট তৈরি করতে, কেবল ব্যবহার করুন W_NEW(classname, .x=1, .y=2,...)। সূচনাটি সি 11 এ প্রবর্তিত স্ট্রাক্ট ইনিশিয়ালাইজের উপর ভিত্তি করে। এটি দুর্দান্তভাবে কাজ করে এবং তালিকাভুক্ত সমস্ত কিছুই শূন্যতে সেট করা আছে।

একটি পদ্ধতি কল করতে, ব্যবহার করুন W_CALL(o,method)(1,2,3)। এটি দেখতে একটি উচ্চতর অর্ডার ফাংশন কলের মতো দেখাচ্ছে তবে এটি কেবল একটি ম্যাক্রো। এটি প্রসারিত ((o)->klass->method(o,1,2,3))যা সত্যিই দুর্দান্ত হ্যাক is

দেখুন ডকুমেন্টেশন এবং কোড নিজেই

যেহেতু ফ্রেমওয়ার্কটিতে কিছু বয়লারপ্লিট কোডের প্রয়োজন হয়, তাই আমি একটি পার্ল স্ক্রিপ্ট (wobject) লিখেছিলাম যা কাজ করে। আপনি যদি এটি ব্যবহার করেন তবে আপনি কেবল লিখতে পারেন

class Point
    public int move_up(int steps)
    public void draw()
    read int x
    read int y

এবং এটি ক্লাস স্পেসিফিকেশন ফাইল, শ্রেণি শিরোনাম এবং একটি সি ফাইল তৈরি করবে, যার মধ্যে Point_impl.cআপনি ক্লাসটি কোথায় প্রয়োগ করবেন includes এটি বেশ কাজের সাশ্রয় করে, যদি আপনার অনেকগুলি সাধারণ ক্লাস থাকে তবে তবুও সবকিছু সি- তে রয়েছে wobject একটি খুব সাধারণ নিয়মিত এক্সপ্রেশন ভিত্তিক স্ক্যানার যা নির্দিষ্ট প্রয়োজনের সাথে খাপ খাইয়ে নেওয়া সহজ, বা স্ক্র্যাচ থেকে পুনরায় লেখার জন্য।



0

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

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