আপনি কিভাবে সি তে একটি ক্লাস বাস্তবায়ন করবেন? [বন্ধ]


139

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

সীমাবদ্ধতা:

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

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

1
কড়া কথা বলতে গেলে, আমাদের দরকার নেই। যাইহোক, সিস্টেমের জটিলতাটি কোডটিকে অভাবনীয় করে তুলেছে। আমার অনুভূতি হ'ল জটিলতা হ্রাস করার সর্বোত্তম উপায় হ'ল কয়েকটি ওওপি ধারণা বাস্তবায়ন করা। 3 মিনিটের মধ্যে যারা প্রতিক্রিয়া জানিয়েছেন তাদের জন্য ধন্যবাদ। আপনি ছেলেরা পাগল এবং দ্রুত!
বেন গার্টনার

8
এটি কেবল আমার নম্র মতামত, তবে ওওপি তাৎক্ষণিকভাবে রক্ষণাবেক্ষণযোগ্য করে তোলে না make এটি পরিচালনা করা সহজ করে তুলতে পারে তবে আরও রক্ষণাবেক্ষণের প্রয়োজন হয় না। আপনার সিতে "নেমস্পেস" থাকতে পারে (অ্যাপাচি পোর্টেবল রানটাইম উপস্থাপিত সমস্ত গ্লোবাল প্রতীক সহ apr_এবং গিলেব g_একটি নেমস্পেস তৈরি করতে তাদের উপসর্গ করে ) এবং ওওপি ছাড়াই অন্যান্য সাংগঠনিক কারণগুলি থাকতে পারে। যদি আপনি যাইহোক অ্যাপটিকে পুনর্গঠন করতে যাচ্ছেন তবে আমি আরও রক্ষণাবেক্ষণযোগ্য পদ্ধতিগত কাঠামোটি নিয়ে আসতে চেষ্টা করার জন্য কিছুটা সময় ব্যয় করার বিষয়টি বিবেচনা করব।
ক্রিস লুটজ

এর আগেও অন্তহীনভাবে আলোচনা করা হয়েছে - আপনি পূর্বের কোনও উত্তর দেখেছেন?
ল্যারি ওয়াতানাবে

এই উত্সটি, যা আমার একটি মুছে ফেলা উত্তরে ছিল, সেগুলিও সহায়ক হতে পারে: প্লেনপডিএফ.কমডেকটস / পিডিএফস / ইওকি.পিডিএফ এটি সি
রুবেন স্টেইনস

উত্তর:


86

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

typedef struct {
  float (*computeArea)(const ShapeClass *shape);
} ShapeClass;

float shape_computeArea(const ShapeClass *shape)
{
  return shape->computeArea(shape);
}

এটি আপনাকে বেস শ্রেণীর "উত্তরাধিকার সূত্রে", এবং একটি উপযুক্ত ফাংশন প্রয়োগ করে একটি শ্রেণি বাস্তবায়ন করতে দেয়:

typedef struct {
  ShapeClass shape;
  float width, height;
} RectangleClass;

static float rectangle_computeArea(const ShapeClass *shape)
{
  const RectangleClass *rect = (const RectangleClass *) shape;
  return rect->width * rect->height;
}

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

void rectangle_new(RectangleClass *rect)
{
  rect->width = rect->height = 0.f;
  rect->shape.computeArea = rectangle_computeArea;
}

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

void rectangle_new_with_lengths(RectangleClass *rect, float width, float height)
{
  rectangle_new(rect);
  rect->width = width;
  rect->height = height;
}

ব্যবহার দেখানোর জন্য এখানে একটি মৌলিক উদাহরণ রয়েছে:

int main(void)
{
  RectangleClass r1;

  rectangle_new_with_lengths(&r1, 4.f, 5.f);
  printf("rectangle r1's area is %f units square\n", shape_computeArea(&r1));
  return 0;
}

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

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


অবজেক্ট-ওরিয়েন্টেড সি লেখার চেষ্টা করতে হয়নি, সাধারণত যে ফাংশনগুলি গ্রহণ করা হয় const ShapeClass *বা const void *যুক্তি হিসাবে তৈরি করা ভাল ? দেখে মনে হবে যে উত্তরসূরিটি উত্তরাধিকার সূত্রে কিছুটা সুন্দর হতে পারে তবে আমি উভয় উপায়ে তর্ক দেখতে পাচ্ছি ...
ক্রিস লুটজ

1
@ ক্রিস: হ্যাঁ, এটি একটি কঠিন প্রশ্ন। : | জিটিকে + (যা জিওজেক্ট ব্যবহার করে) যথাযথ শ্রেণি, অর্থাৎ রেক্টাঙ্গেলক্লাস * ব্যবহার করে। এর অর্থ আপনার প্রায়শই কাস্ট করতে হয় তবে তারা সহজেই ম্যাক্রোগুলিকে সহায়তা করে যাতে আপনি সবসময় কেবলমাত্র সাবস্ক্লাস (পি) ব্যবহার করে বেসকলাস * পি সাবস্ক্লাস * এ কাস্ট করতে পারেন।
বিনোদন

1
আমার কম্পাইলার কোডের দ্বিতীয় লাইন ব্যর্থ হলে: float (*computeArea)(const ShapeClass *shape);এই বলে যে ShapeClassএকটি অজানা প্রকার।
ড্যানিয়েলস্যাঙ্ক

@ ড্যানিয়েলস্যাঙ্ক যা 'টাইপেডেফ স্ট্রাক্ট'-এর দ্বারা প্রয়োজনীয় ফরোয়ার্ড ঘোষণার অভাবের কারণে হয় (প্রদত্ত উদাহরণে প্রদর্শিত হয়নি)। কারণ structরেফারেন্স নিজেই, এটি সংজ্ঞায়িত হওয়ার আগে এটি ঘোষণার প্রয়োজন । এই হয় Lundin এর উত্তরে একটি উদাহরণ এখানে ব্যাখ্যা । ফরওয়ার্ড ঘোষণার অন্তর্ভুক্ত করার জন্য উদাহরণটি সংশোধন করা আপনার সমস্যার সমাধান করা উচিত; typedef struct ShapeClass ShapeClass; struct ShapeClass { float (*computeArea)(const ShapeClass *shape); };
এস হুইটেকার

যখন আয়তক্ষেত্রের একটি ফাংশন থাকে যা সমস্ত আকারগুলি করে না What উদাহরণস্বরূপ, get_corners ()। একটি চেনাশোনা এটি প্রয়োগ করে না তবে একটি আয়তক্ষেত্র হতে পারে। আপনি উত্তরাধিকার সূত্রে পিতৃত শ্রেণীর অংশ নয় এমন কোনও ফাংশনে আপনি কীভাবে অ্যাক্সেস করবেন?
ওটাস

24

হোম ওয়ার্কের জন্য আমাকে একবারও এটি করতে হয়েছিল। আমি এই পদ্ধতির অনুসরণ করেছি:

  1. আপনার ডেটা সদস্যদের একটি কাঠামোয় সংজ্ঞা দিন।
  2. আপনার ক্রিয়াকলাপের সদস্যদের সংজ্ঞা দিন যা আপনার স্ট্রাক্টে প্রথম যুক্তি হিসাবে একটি পয়েন্টার নেয়।
  3. এটি একটি শিরোনামে করুন এবং একটি গ। কাঠামো সংজ্ঞা এবং ফাংশন ঘোষণার জন্য শিরোনাম, বাস্তবায়নের জন্য সি।

একটি সাধারণ উদাহরণ এটি হবে:

/// Queue.h
struct Queue
{
    /// members
}
typedef struct Queue Queue;

void push(Queue* q, int element);
void pop(Queue* q);
// etc.
/// 

এটি আমি অতীতে করেছি, তবে প্রয়োজনীয়ভাবে .c বা .h ফাইলে ফাংশন প্রোটোটাইপ রেখে ফেকিং স্কোপ যুক্ত করার সাথে (যেমনটি আমি আমার উত্তরে উল্লেখ করেছি)।
টেলর লিজ

আমি এটি পছন্দ করি, স্ট্রাক্ট ঘোষণা সমস্ত মেমরি বরাদ্দ করে। কোনও কারণে আমি ভুলে গিয়েছিলাম এটি ভালভাবে কাজ করবে।
বেন গার্টনার

আমার মনে হয় আপনার typedef struct Queue Queue;সেখানে একটি দরকার ।
ক্রেগ ম্যাককুইন

3
বা কেবল টাইপিডের স্ট্রাক্ট {/ * সদস্য * /} সারি;
ব্রুকস মুসা

# ক্রেইগ: আপডেট করা অনুস্মারকটির জন্য ধন্যবাদ।
এরিলেন্ডার

12

আপনি যদি কেবল একটি শ্রেণি চান তবে struct"অবজেক্টস" ডেটা হিসাবে একটি অ্যারের ব্যবহার করুন এবং তাদেরকে "সদস্য" ফাংশনে পয়েন্টার দিন। ক্লায়েন্ট কোড থেকে প্রয়োগটি গোপন করার জন্য আপনি typedef struct _whatever Whateverঘোষণার আগে ব্যবহার করতে পারেন struct _whatever। এই জাতীয় "অবজেক্ট" এবং সি স্ট্যান্ডার্ড লাইব্রেরির মধ্যে কোনও পার্থক্য নেইFILE অবজেক্টের ।

যদি আপনি উত্তরাধিকার এবং ভার্চুয়াল ফাংশন সহ একাধিক শ্রেণি চান, তবে স্ট্রাক্টের সদস্য হিসাবে ফাংশনগুলিতে পয়েন্টার বা ভার্চুয়াল ফাংশনগুলির একটি টেবিলের জন্য একটি ভাগ করে নেওয়া পয়েন্টারটি সাধারণ। GObject গ্রন্থাগার উভয় এটি এবং হয় typedef কৌতুক ব্যবহার করে, এবং ব্যাপকভাবে ব্যবহার করা হয়।

অনলাইনে উপলব্ধ এই প্রযুক্তির উপর একটি বইও রয়েছে - এএনএসআই সি এর সাথে অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিং


1
শান্ত! সিও-তে ওওপিতে বইয়ের জন্য অন্য কোনও সুপারিশ? নাকি সি তে অন্য কোন আধুনিক ডিজাইনের কৌশল? (বা এম্বেড হওয়া সিস্টেম?)
বেন গার্টনার

7

আপনি GOBject এ একবার দেখতে পারেন। এটি একটি ওএস লাইব্রেরি যা আপনাকে কোনও অবজেক্ট করার ভারবোস উপায় দেয়।

http://library.gnome.org/devel/gobject/stable/


1
খুব আকাঙ্ক্ষিত. লাইসেন্সিং সম্পর্কে কেউ জানেন? কর্মক্ষেত্রে আমার উদ্দেশ্যগুলির জন্য, কোনও প্রকল্পে একটি ওপেন সোর্স লাইব্রেরি ফেলে দেওয়া সম্ভবত আইনী দৃষ্টিকোণ থেকে কাজ করছে না।
বেন গার্টনার

জিটিকে +, এবং সমস্ত লাইব্রেরি যা এই প্রকল্পের অংশ (জিওজেক্ট সহ), জিএনইউ এলজিপিএল এর অধীনে লাইসেন্সযুক্ত, যার অর্থ আপনি মালিকানাধীন সফ্টওয়্যার থেকে তাদের সাথে লিঙ্ক করতে পারেন। যদিও এম্বেড করা কাজের জন্য এটি সম্ভব হবে কিনা তা আমি জানি না।
ক্রিস লুটজ

7

সি ইন্টারফেস এবং বাস্তবায়ন: পুনরায় ব্যবহারযোগ্য সফ্টওয়্যার তৈরির কৌশল , ডেভিড আর হ্যানসন

http://www.informit.com/store/product.aspx?isbn=0201498413

এই বইটি আপনার প্রশ্নটি কাভার করার একটি দুর্দান্ত কাজ করে। এটি অ্যাডিসন ওয়েসলি পেশাদার কম্পিউটিং সিরিজে রয়েছে series

মৌলিক দৃষ্টান্তটি এরকম কিছু:

/* for data structure foo */

FOO *myfoo;
myfoo = foo_create(...);
foo_something(myfoo, ...);
myfoo = foo_append(myfoo, ...);
foo_delete(myfoo);

5

সি-তে ওওপি কীভাবে করা উচিত তার একটি সহজ উদাহরণ আমি দেব I

/// Object.h
typedef struct Object {
    uuid_t uuid;
} Object;

int Object_init(Object *self);
uuid_t Object_get_uuid(Object *self);
int Object_clean(Object *self);

/// Person.h
typedef struct Person {
    Object obj;
    char *name;
} Person;

int Person_init(Person *self, char *name);
int Person_greet(Person *self);
int Person_clean(Person *self);

/// Object.c
#include "object.h"

int Object_init(Object *self)
{
    self->uuid = uuid_new();

    return 0;
}
uuid_t Object_get_uuid(Object *self)
{ // Don't actually create getters in C...
    return self->uuid;
}
int Object_clean(Object *self)
{
    uuid_free(self->uuid);

    return 0;
}

/// Person.c
#include "person.h"

int Person_init(Person *self, char *name)
{
    Object_init(&self->obj); // Or just Object_init(&self);
    self->name = strdup(name);

    return 0;
}
int Person_greet(Person *self)
{
    printf("Hello, %s", self->name);

    return 0;
}
int Person_clean(Person *self)
{
    free(self->name);
    Object_clean(self);

    return 0;
}

/// main.c
int main(void)
{
    Person p;

    Person_init(&p, "John");
    Person_greet(&p);
    Object_get_uuid(&p); // Inherited function
    Person_clean(&p);

    return 0;
}

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

এটি এবং নির্মাতা, ডিস্ট্রাক্টর, বরাদ্দ এবং ডেলোক্যারিয়ন ফাংশনগুলির জন্য কিছু নামকরণের সম্মেলন (আমি প্রস্তাব দিচ্ছি, পরিষ্কার, নতুন, ফ্রি) আপনাকে দীর্ঘ পথ পাবে।

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


দাবি অস্বীকার: স্মার্টফোনে লিখিত সমস্ত কোড। যেখানে প্রয়োজন ত্রুটি পরীক্ষাগুলি যুক্ত করুন। বাগের জন্য পরীক্ষা করুন।
yyny

4

structএকটি শ্রেণীর ডেটা সদস্যদের অনুকরণ করতে একটি ব্যবহার করুন । পদ্ধতির সুযোগের ক্ষেত্রে আপনি .c ফাইলে ব্যক্তিগত ফাংশন প্রোটোটাইপ এবং .h ফাইলে সর্বজনীন ফাংশন রেখে ব্যক্তিগত পদ্ধতিগুলি অনুকরণ করতে পারেন ।


4
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <uchar.h>

/**
 * Define Shape class
 */
typedef struct Shape Shape;
struct Shape {
    /**
     * Variables header...
     */
    double width, height;

    /**
     * Functions header...
     */
    double (*area)(Shape *shape);
};

/**
 * Functions
 */
double calc(Shape *shape) {
        return shape->width * shape->height;
}

/**
 * Constructor
 */
Shape _Shape() {
    Shape s;

    s.width = 1;
    s.height = 1;

    s.area = calc;

    return s;
}

/********************************************/

int main() {
    Shape s1 = _Shape();
    s1.width = 5.35;
    s1.height = 12.5462;

    printf("Hello World\n\n");

    printf("User.width = %f\n", s1.width);
    printf("User.height = %f\n", s1.height);
    printf("User.area = %f\n\n", s1.area(&s1));

    printf("Made with \xe2\x99\xa5 \n");

    return 0;
};

3

আপনার ক্ষেত্রে ক্লাসের ভাল আনুমানিকতা একটি এডিটি হতে পারে । তবে তবুও তা এক রকম হবে না।


1
যে কেউ একটি বিমূর্ত ডেটা টাইপ এবং একটি শ্রেণীর মধ্যে একটি সংক্ষিপ্ত পার্থক্য দিতে পারেন? আমি সবসময় দুটি ধারণার সাথে নিবিড়ভাবে সংযুক্ত হয়েছি।
বেন গার্টনার

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

3

আমার কৌশলটি হ'ল:

  • শ্রেণীর জন্য সমস্ত কোড একটি পৃথক ফাইলে সংজ্ঞায়িত করুন
  • শ্রেণীর জন্য সমস্ত ইন্টারফেস একটি পৃথক শিরোনাম ফাইলে সংজ্ঞায়িত করুন
  • সমস্ত সদস্যের ফাংশন একটি "ClassHandle" নেয় যা উদাহরণস্বরূপ (o.foo () এর পরিবর্তে), ফো foo (ওহ্যান্ডল) কল করে
  • কন্সট্রাক্টর মেমরি বরাদ্দ কৌশলটির উপর ভিত্তি করে ClassInit (ClassHandle h, int x, int y, ...) বা ClassHandle ClassInit (int x, int y, ...) দিয়ে একটি ক্রিয়াকলাপ প্রতিস্থাপন করা হয়
  • সমস্ত সদস্যের ভেরিয়েবলগুলি ক্লাস ফাইলে একটি স্ট্যাটিক স্ট্রাক্টের সদস্য হিসাবে স্টোর করা হয়, এটি ফাইলটিতে আবদ্ধ করে, বাইরের ফাইলগুলিকে অ্যাক্সেস করা থেকে বিরত করে
  • পূর্বনির্ধারিত হ্যান্ডলগুলি (ইন্টারফেসে দৃশ্যমান) বা তাত্ক্ষণিকভাবে স্থাপন করা যেতে পারে এমন বস্তুর একটি নির্দিষ্ট সীমা সহ বস্তুগুলি উপরের স্ট্যাটিক কাঠামোর একটি অ্যারেতে সংরক্ষণ করা হয়
  • যদি দরকারী হয় তবে শ্রেণিতে এমন সর্বজনীন ফাংশন থাকতে পারে যা অ্যারের মধ্য দিয়ে লুপ হয়ে যাবে এবং সমস্ত তাত্ক্ষণিক বস্তুর ফাংশনগুলিকে কল করবে (রানআল () প্রতিটি রানকে কল করে (ওহ্যান্ডল)
  • একটি ডিনিট (ক্লাসহ্যান্ডল এইচ) ফাংশন গতিশীল বরাদ্দ কৌশলটিতে বরাদ্দ হওয়া মেমরি (অ্যারে সূচক) মুক্ত করে

এই পদ্ধতির পরিবর্তনের ক্ষেত্রে কেউ কি কোনও সমস্যা, গর্ত, সম্ভাব্য সমস্যা বা লুকানো সুবিধা / অসুবিধা দেখতে পাচ্ছে? আমি যদি কোনও নকশা পদ্ধতি পুনরায় উদ্ভাবন করি (এবং আমি ধরে নিই যে আমার অবশ্যই হওয়া উচিত), আপনি কি আমাকে এর নামের দিকে নির্দেশ করতে পারেন?


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

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

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

3

আরো দেখুন এই উত্তর এবং এই এক দেখুন

এটা সম্ভব. এটিকে সবসময় একটি ভাল ধারণা বলে মনে হয় তবে পরে এটি রক্ষণাবেক্ষণের দুঃস্বপ্নে পরিণত হয়। আপনার কোড কোড টুকরো টুকরো টুকরো টুকরো করে সমস্ত কিছু এক সাথে বেঁধে রাখে। আপনি যদি ফাংশন পয়েন্টার ব্যবহার করেন তবে কোনও নতুন প্রোগ্রামার কোড পড়তে এবং বুঝতে প্রচুর সমস্যা পাবেন যেহেতু ফাংশন কী বলা হয় তা স্পষ্ট হবে না।

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

যেহেতু আপনার সমস্ত প্রস্তুত রক্ষণাবেক্ষণের সমস্যা রয়েছে আমি পরিষ্কার করে দেব।


2

আমার পদ্ধতিটি হ'ল structএবং সমস্ত প্রাথমিকভাবে সম্পর্কিত ফাংশনগুলিকে একটি পৃথক উত্স ফাইল (গুলি) এ সরানো হবে যাতে এটি "বহনযোগ্য" ব্যবহার করা যায়।

আপনার সংকলক উপর নির্ভর করে, আপনি ফাংশনগুলি অন্তর্ভুক্ত করতে সক্ষম হতে পারেন structতবে এটি একটি খুব সংকলক-নির্দিষ্ট এক্সটেনশন এবং আমি নিয়মিত ব্যবহৃত স্ট্যান্ডার্ডটির শেষ সংস্করণটির সাথে কোনও সম্পর্ক নেই :)


2
ফাংশন পয়েন্টার সব ভাল। আমরা এগুলিকে একটি সন্ধানের টেবিলের সাহায্যে বড় স্যুইচ স্টেটমেন্টগুলি প্রতিস্থাপন করতে ব্যবহার করি।
বেন গার্টনার

2

প্রথম সি ++ সংকলক আসলে একটি প্রিপ্রসেসর ছিল যা সি ++ কোডটি সিতে অনুবাদ করে was

সুতরাং সি তে ক্লাস করা খুব সম্ভব আপনি একটি পুরানো সি ++ প্রিপ্রসেসর চেষ্টা করতে পারেন এবং এটি কী ধরণের সমাধান তৈরি করে তা দেখতে পারেন।


তা হবে cfront; এটি সমস্যায় পড়ে যখন সি ++ এ ব্যতিক্রম যুক্ত হয়েছিল - ব্যতিক্রমগুলি পরিচালনা করা তুচ্ছ নয়।
জোনাথন লেফলার

2

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


1

আপনি কি ভার্চুয়াল পদ্ধতি চান?

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

আপনি যদি ভার্চুয়াল পদ্ধতিগুলি রাখতে চান এটি আরও জটিল হয়ে ওঠে। মূলত আপনাকে প্রতিটি স্ট্রাক্টে আপনার নিজস্ব ভিটিবেল প্রয়োগ করতে হবে এবং কোন ফাংশনটি ডাকা হবে তার উপর নির্ভর করে ভিটিবেলে ফাংশন পয়েন্টার নির্ধারণ করতে হবে। তারপরে আপনার স্ট্রাক্টের মধ্যে ফাংশন পয়েন্টারগুলির একটি সেট দরকার যা ঘুরে ভিটিবেলে ফাংশন পয়েন্টারটিকে কল করে। এটি মূলত সি ++ কী করে।

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


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

0

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

এছাড়াও, আপনি যদি সি ব্যবহার করতে পারেন তবে আপনি সম্ভবত সি ++ ব্যবহার করতে পারেন এবং ক্লাস পেতে পারেন।


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