সিটিতে অবজেক্ট-ভিত্তিক কোড লেখার কয়েকটি উপায় কী কী? বিশেষত বহুত্ববাদ সম্পর্কে।
এই স্ট্যাক ওভারফ্লো প্রশ্নটি সিটিতে অবজেক্ট-ওরিয়েন্টেশনটিও দেখুন ।
সিটিতে অবজেক্ট-ভিত্তিক কোড লেখার কয়েকটি উপায় কী কী? বিশেষত বহুত্ববাদ সম্পর্কে।
এই স্ট্যাক ওভারফ্লো প্রশ্নটি সিটিতে অবজেক্ট-ওরিয়েন্টেশনটিও দেখুন ।
উত্তর:
হ্যাঁ. প্রকৃতপক্ষে অ্যাক্সেল শ্রেইনার তাঁর "অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিং ইন এএনএসআই-সি" বইটি বিনামূল্যে সরবরাহ করেছেন যা বিষয়টিকে পুরোপুরিভাবে কভার করে।
যেহেতু আপনি বহুবর্ষ সম্পর্কে কথা বলছেন তবে হ্যাঁ, আপনি পারেন, সি ++ আসার কয়েক বছর আগে আমরা সেই ধরণের জিনিসগুলি করছিলাম।
মূলত আপনি একটি ব্যবহার 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
সুতরাং আপনি দেখতে পাচ্ছেন যে উপ-শ্রেণীর উপর নির্ভর করে বিভিন্ন ফাংশন ডাকা হচ্ছে।
tCommClass
নামটি পুনরায় নামকরণ করা হবে tCommVT
এবং কোনও tCommClass
স্ট্রাক্টে কেবলমাত্র ডেটা ক্ষেত্র এবং tCommVT vt
"একমাত্র এবং কেবলমাত্র" ভার্চুয়াল-টেবিলের দিকে নির্দেশ করে একটি একক ক্ষেত্র থাকবে have প্রতিটি দৃষ্টান্তের সাথে চারদিকে সমস্ত পয়েন্টার বহন করা অপ্রয়োজনীয় ওভারহেড যুক্ত করে এবং আপনি সি ++, আইএমএইচও-র চেয়ে জাভাস্ক্রিপ্টে কীভাবে স্টাফ করবেন তা আরও সাদৃশ্যপূর্ণ।
নেমস্পেসগুলি প্রায়শই করে করা হয়:
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
}
আমি ডেস্ট্রাক্টর বা মুছে ফেলিনি, তবে এটি একই ধাঁচ অনুসরণ করে।
এই_এই_এখানে_আস_আন_ উদাহরণ_একটি স্ট্যাটিক ক্লাস ভেরিয়েবলের মতো - এক ধরণের সমস্ত দৃষ্টান্তের মধ্যে ভাগ করে নেওয়া। সমস্ত পদ্ধতি সত্যই স্থিতিশীল, ব্যতীত কিছু এটি * নেয়
st->my_type->push(st, thing2);
পরিবর্তেst->my_type.push(st, thing2);
struct stack_type my_type;
পরিবর্তেstruct stack_type * my_type;
Class
স্ট্রাক্ট কেমন? এটি ওও সি সি ++ এর চেয়ে আরও গতিশীল করে তুলবে । কীভাবে? যাইহোক, +1।
আমি বিশ্বাস করি যে এটি নিজস্বভাবে কার্যকর হওয়ার পাশাপাশি সি-তে ওওপি বাস্তবায়ন করা ওওপি শেখার এবং এর অভ্যন্তরীণ কার্যকারিতা বোঝার একটি দুর্দান্ত উপায় । অনেক প্রোগ্রামারদের অভিজ্ঞতা দেখিয়েছে যে দক্ষতার সাথে এবং আত্মবিশ্বাসের সাথে কোনও কৌশল ব্যবহার করতে একজন প্রোগ্রামারকে অবশ্যই বুঝতে হবে যে অন্তর্নিহিত ধারণাগুলি কীভাবে চূড়ান্তভাবে প্রয়োগ করা হয়। সি তে অনুকরণকারী ক্লাস, উত্তরাধিকার এবং পলিমারফিজম কেবল এটি শেখায়।
মূল প্রশ্নের উত্তর দেওয়ার জন্য, এখানে কয়েকটি সংস্থান দেওয়া আছে যা সিতে ওওপি কীভাবে করতে হয় তা শেখায়:
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 থেকে পাওয়া যায়
আমি এটা সম্পন্ন দেখেছি। আমি এটি সুপারিশ করব না। সি ++ প্রাথমিকভাবে এইভাবে একটি প্রিপ্রসেসর হিসাবে শুরু করেছিলেন যা মধ্যবর্তী পদক্ষেপ হিসাবে সি কোড তৈরি করে।
মূলত আপনি যা করছেন তা হ'ল আপনার ফাংশনের রেফারেন্সগুলি সংরক্ষণ করার জন্য আপনার সমস্ত পদ্ধতির জন্য প্রেরণ টেবিল তৈরি করা। কোনও শ্রেণীর বিভাজন জানানোতে এই প্রেরণের টেবিলটি অনুলিপি করা এবং আপনি যে নতুন প্রবেশপথকে ওভাররাইড করতে চেয়েছিলেন তা প্রতিস্থাপন করতে পারে, যদি আপনার নতুন "পদ্ধতিগুলি" বেস পদ্ধতিটি চালু করতে চায় তবে মূল পদ্ধতিটি কল করতে হবে। অবশেষে, আপনি সি ++ এর পুনর্লিখন শেষ করবেন।
glib
সিতে উদ্দেশ্যমূলকভাবে লেখা হয় না ?
নিশ্চিত যে সম্ভব। এটি জিওজেক্ট , ফ্রেমওয়ার্ক যা সমস্ত জিটিকে + করে এবং GNOME- র নির্ভর করে, যা করে।
সি স্টিডিও ফাইল সাব-লাইব্রেরি আনড্রাক্ট্রেটেড সি-তে কীভাবে বিমূর্ততা, এনক্যাপসুলেশন এবং মডুলারিটি তৈরি করতে পারে তার একটি দুর্দান্ত উদাহরণ is
উত্তরাধিকার এবং বহুবিকতা - অন্যান্য দিকগুলি প্রায়শই ওওপি-র প্রয়োজনীয় হিসাবে বিবেচিত হয় - তারা যে প্রতিশ্রুতি দেয় উত্পাদনশীলতা লাভগুলি সরবরাহ করে না এবং যুক্তিযুক্ত যুক্তি তৈরি করা হয়েছে যে তারা আসলে সমস্যার ডোমেন সম্পর্কে বিকাশ এবং চিন্তাভাবনায় বাধা দিতে পারে।
একটি প্রাণী এবং কুকুরের সাথে তুচ্ছ উদাহরণ: আপনি সি ++ এর ভিটিবেল প্রক্রিয়া (মূলত যাইহোক) মিরর করুন। আপনি বরাদ্দ এবং ইনস্ট্যান্টেশন পৃথক করেও (এনিমেল_আলোক, এনিমেল_নিউ) যাতে আমরা একাধিকবার ম্যালোক () কল করি না। আমাদের অবশ্যই স্পষ্টভাবে পাস করতে হবে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
সি তে সম্ভব নয়
পরীক্ষা করে দেখুন GObject । এটি সি এর ওও হতে হবে এবং আপনি যা সন্ধান করছেন তার একটি বাস্তবায়ন। আপনি যদি সত্যিই ওও চান, তবে সি ++ বা অন্য কোনও ওওপি ভাষার সাথে যান। আপনি যদি ওও ভাষাগুলির সাথে ডিল করতে অভ্যস্ত হন তবে GObject এর সাথে কাজ করা সত্যিই কঠিন হতে পারে তবে কোনও কিছুর মতোই আপনি সম্মেলন এবং প্রবাহে অভ্যস্ত হয়ে যাবেন।
এটি পড়া আকর্ষণীয় হয়েছে। আমি নিজেই একই প্রশ্নটি ভাবছি এবং এটি সম্পর্কে চিন্তাভাবনার সুবিধাগুলি হ'ল:
অপ-ওওপি ভাষায় কীভাবে ওওপি ধারণাগুলি প্রয়োগ করা যায় তা কল্পনা করার চেষ্টা করা আমাকে ওওপি ভাষার শক্তি বুঝতে সহায়তা করে (আমার ক্ষেত্রে, সি ++)। প্রদত্ত প্রকারের অ্যাপ্লিকেশনটির জন্য সি বা সি ++ ব্যবহার করবেন কিনা সে সম্পর্কে এটি আমাকে আরও ভাল রায় দিতে সহায়তা করে - যেখানে একটির সুবিধাগুলি অপরটির চেয়ে বেশি ওজনযুক্ত।
এই সম্পর্কিত তথ্য এবং মতামতের জন্য আমার ওয়েব ব্রাউজিংয়ে আমি এমন একজন লেখককে পেয়েছি যিনি এমবেডেড প্রসেসরের জন্য কোড লিখছিলেন এবং কেবলমাত্র একটি সি সংকলক উপলব্ধ ছিল: http://www.eetimes.com/discussion/other/4024626/Object- ওরিয়েন্টড -C-তৈরি করা-ফাউন্ডেশন-ক্লাস-পার্ট -1
তার ক্ষেত্রে, প্লেইন সি-তে OOP ধারণাগুলি বিশ্লেষণ ও মানিয়ে নেওয়া একটি বৈধ অনুসারী ছিল। দেখা যাচ্ছে যে ওভারহেডের পারফরম্যান্সের কারণে সিটিতে সেগুলি প্রয়োগ করার চেষ্টা করার ফলে তিনি কিছু ওওপি ধারণার ত্যাগ করতে প্রস্তুত ছিলেন them
আমি যে পাঠ গ্রহণ করেছি তা হ্যাঁ এটি একটি নির্দিষ্ট ডিগ্রিতে করা যেতে পারে এবং হ্যাঁ, এটি চেষ্টা করার কিছু ভাল কারণ রয়েছে।
শেষ পর্যন্ত, মেশিনটি স্ট্যাক পয়েন্টার বিটগুলিকে ঝাঁকুনি দিচ্ছে, যা প্রোগ্রামটিকে পাল্টা ঝাঁপ দাও এবং মেমরি অ্যাক্সেসের ক্রিয়াকলাপ গণনা করছে। দক্ষতার দৃষ্টিকোণ থেকে, আপনার প্রোগ্রাম দ্বারা এই গণনাগুলির যত কম হয়েছে, তত ভাল ... তবে কখনও কখনও আমাদের কেবল এই কর দিতে হয় যাতে আমরা আমাদের প্রোগ্রামটি এমনভাবে পরিচালনা করতে পারি যা এটি মানুষের ত্রুটির পক্ষে কমপক্ষে সংবেদনশীল হয়ে ওঠে। ওওপি ভাষা সংকলক উভয় দিক অপ্টিমাইজ করার চেষ্টা করে। প্রোগ্রামারকে সি এর মতো ভাষায় এই ধারণাগুলি বাস্তবায়নে আরও বেশি যত্নবান হতে হবে
অ্যাপল এর কোর ফাউন্ডেশন সেট এর API এর জন্য ডকুমেন্টেশনগুলি দেখতে আপনাকে সহায়ক হতে পারে। এটি একটি খাঁটি সি এপিআই, তবে ধরণের অনেকগুলি উদ্দেশ্য-সি অবজেক্টের সমতুল্য হয়ে থাকে।
আপনি নিজেই ওজেক্টিভ-সি এর নকশাটি দেখতে সহায়ক হতে পারেন। এটি সি ++ থেকে কিছুটা পৃথক যে বস্তুর সিস্টেমটি সি ফাংশনগুলির ক্ষেত্রে যেমন সংজ্ঞায়িত করা হয়, যেমন objc_msg_send
কোনও বস্তুর কোনও পদ্ধতিতে কল করা। সংকলকটি বর্গাকার বন্ধনী সিনট্যাক্সটিকে সেই ফাংশন কলগুলিতে অনুবাদ করে, তাই আপনাকে এটি জানতে হবে না, তবে আপনার প্রশ্ন বিবেচনা করে আপনি এটি কীভাবে হুডের নীচে কাজ করে তা শেখার পক্ষে দরকারী হতে পারে।
বেশ কয়েকটি কৌশল ব্যবহার করা যেতে পারে। সবচেয়ে গুরুত্বপূর্ণটি হল কীভাবে প্রকল্পটি বিভক্ত করা যায় 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
আমার প্রোগ্রামগুলিতে করি, এটি নিশ্চিত করার জন্য যে আমার প্রোগ্রামটি সি ++ তে সংকলন করছে না এবং এতে আমার সিনট্যাক্স হাইলাইটিং এডিটরটিতে অন্য রঙে থাকার চমৎকার সম্পত্তি রয়েছে।
এফইও_স্ট্রাক্টের ক্ষেত্রগুলি একটি মডিউলে সংশোধন করা যেতে পারে এবং অন্য মডিউলটিকে এখনও ব্যবহারযোগ্য হওয়ার জন্য পুনরায় সংকলনের প্রয়োজন হয় না।
এই শৈলীর সাহায্যে আমি ইতিমধ্যে ওওপি (ডেটা এনক্যাপসুলেশন) সুবিধার একটি বড় অংশ হ্যান্ডেল করেছি। ফাংশন পয়েন্টারগুলি ব্যবহার করে, উত্তরাধিকারের মতো কোনও কিছু কার্যকর করা এমনকি সহজ তবে সত্যই, এটি সত্যিই কেবল বিরল।
typedef struct FOO_type FOO_type
শিরোনামটিতে শূন্যতার জন্য টাইপেফের পরিবর্তে করেন তবে আপনার কাঠামোটি প্রকাশ না করেও আপনি টাইপ চেকিংয়ের অতিরিক্ত সুবিধা পাবেন।
আপনি এটি ফাংশন পয়েন্টার ব্যবহার করে জাল করতে পারেন, এবং বাস্তবে, আমি মনে করি যে সি ++ প্রোগ্রামগুলি সিতে সংকলন করা তাত্ত্বিকভাবে সম্ভব is
তবে, উদাহরণস্বরূপ এমন একটি ভাষা বেছে নেওয়ার পরিবর্তে কোনও ভাষায় দৃষ্টান্ত জোর দিয়ে বোঝা যায় না।
অবজেক্ট ওরিয়েন্টেড সি, কাজটি করা যেতে পারে, আমি কোরিয়ায় উত্পাদনের ক্ষেত্রে এই ধরণের কোড দেখেছি এবং আমি বছরের পর বছরগুলি দেখেছি এটি সবচেয়ে ভয়ঙ্কর দৈত্য ছিল (এটি গত বছরের মতো ছিল (2007) যে কোডটি দেখেছি)। সুতরাং হ্যাঁ এটি করা যেতে পারে, এবং হ্যাঁ লোকেরা এটি আগেও করেছিল এবং এখনও এবং এটি আজ এবং যুগেও করে। তবে আমি সি ++ বা অবজেক্টিভ-সি সুপারিশ করবো, দুটিই ভিন্ন ভিন্ন দৃষ্টান্তের সাথে অবজেক্ট অরিয়েন্টেশন দেওয়ার উদ্দেশ্যে, সি থেকে জন্ম নেওয়া ভাষা।
আপনি যদি নিশ্চিত হন যে সমস্যার সমাধানের জন্য আপনি একটি ওওপি পদ্ধতির চেয়েও উন্নত, তবে কেন আপনি এটি একটি অ-ওওপি ভাষায় সমাধান করার চেষ্টা করবেন? দেখে মনে হচ্ছে আপনি কাজের জন্য ভুল সরঞ্জামটি ব্যবহার করছেন। সি ++ বা অন্য কোনও অবজেক্ট-ভিত্তিক সি বৈকল্পিক ভাষা ব্যবহার করুন।
আপনি যদি জিজ্ঞাসা করছেন যে আপনি ইতিমধ্যে সিটিতে লিখিত একটি বিদ্যমান বৃহত প্রকল্পের কোডিং শুরু করছেন, তবে আপনার নিজের (বা অন্য কারও) ওওপি দৃষ্টান্তকে প্রকল্পের অবকাঠামোতে জোর করার চেষ্টা করা উচিত নয়। প্রকল্পে ইতিমধ্যে উপস্থিত নির্দেশিকা অনুসরণ করুন। সাধারণভাবে, ক্লিন এপিআই এবং বিচ্ছিন্ন লাইব্রেরি এবং মডিউলগুলি পরিষ্কার ওওপিও- ইশ ডিজাইনের দিকে অনেক এগিয়ে যাবে ।
তাহলে, এর পরে, আপনি কি সত্যিই গলি সি করছেন সেট করা, পড়া এই (পিডিএফ)।
হ্যা, তুমি পারো. লোকেরা সি ++ বা উদ্দেশ্য-সি এর আগে অবজেক্ট-ওরিয়েন্টেড সি লিখছিল ঘটনাস্থলে আসার লিখছিল। সি ++ এবং অবজেক্টিভ-সি উভয় অংশেই সিটিতে ব্যবহৃত কিছু ওও ধারণাগুলি গ্রহণ এবং ভাষার অংশ হিসাবে আনুষ্ঠানিক করার চেষ্টা করেছিল।
এখানে একটি খুব সহজ প্রোগ্রাম যা দেখায় আপনি কীভাবে এমন কিছু তৈরি করতে পারেন যা দেখতে দেখতে একটি পদ্ধতি কল (এটি করার আরও ভাল উপায় আছে 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;
}
যোগ করার জন্য একটি ছোট ওওসি কোড:
#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;
}
আমি এক বছর ধরে এটি খনন করছি:
জিওজেক্ট সিস্টেমটি খাঁটি সি দিয়ে ব্যবহার করা শক্ত হওয়ায় আমি সি দিয়ে ওও স্টাইলটি সহজ করতে কিছু সুন্দর ম্যাক্রো লেখার চেষ্টা করেছি 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। ডক লেখার জন্য আমার কাছে পর্যাপ্ত সময় নেই, তবে চীনা ভাষায় ডকটি আরও ভাল।
জিম লারসনের 1996 এর টক সেকশন 312 প্রোগ্রামিং লঞ্চটাইম সেমিনারে এখানে দেওয়া উত্তরাধিকারের উদাহরণ রয়েছে : উচ্চ এবং নিম্ন স্তরের সি ।
কোন নিবন্ধ বা বই সি তে ওওপি ধারণা ব্যবহার করা ভাল?
ডেভ হ্যানসনের সি ইন্টারফেস এবং ইমপ্লিমেনটেসন হয় চমৎকার এনক্যাপস্যুলেশন ও নামকরণের উপর এবং ফাংশন পয়েন্টার ব্যবহারের উপর খুব ভালো। ডেভ উত্তরাধিকার অনুকরণ করার চেষ্টা করে না।
একটি জিনিস যা আপনি করতে চাইতে পারেন তা হ'ল এক্স উইন্ডোটির জন্য এক্সটি সরঞ্জামকিট বাস্তবায়ন সন্ধান করা । অবশ্যই এটি দাঁতে দীর্ঘ হয়ে চলেছে, তবে ব্যবহৃত অনেকগুলি কাঠামো traditionalতিহ্যবাহী সি এর মধ্যে ওও ফ্যাশনে কাজ করার জন্য ডিজাইন করা হয়েছিল সাধারণত এটির অর্থ এখানে এবং সেখানে একটি অতিরিক্ত স্তর যুক্ত করা এবং একে অপরের উপর রাখার জন্য কাঠামোগত নকশা তৈরি করা।
আপনি সি তে অবস্থিত ওওর পথে সত্যিই প্রচুর পরিমাণে এটি করতে পারেন, যদিও এটি বেশ কয়েকবার মনে হলেও ওও ধারণাগুলি মন থেকে সম্পূর্ণরূপে গঠিত হয়নি #include<favorite_OO_Guru.h>
। তারা সত্যই সময়ের প্রতিষ্ঠিত সেরা অনুশীলনের অনেকগুলি গঠন করেছিল। ওও ভাষা এবং সিস্টেমগুলি কেবলমাত্র দিনের প্রোগ্রামিং জিটজিস্টের পাতিত এবং প্রসারিত অংশ।
প্রশ্নের উত্তরটি হ্যাঁ, আপনি পারবেন '।
অবজেক্ট-ওরিয়েন্টেড সি (ওওসি) কিটটি তাদের জন্য যাঁরা কোনও অবজেক্ট-ভিত্তিক পদ্ধতিতে প্রোগ্রাম করতে চান, তবে ভাল পুরানো সিটিতেও আঁটেন। ওওসি ক্লাস, একক এবং একাধিক উত্তরাধিকার, ব্যতিক্রম হ্যান্ডলিং প্রয়োগ করে।
বৈশিষ্ট্য
Only কেবল সি ম্যাক্রো এবং ফাংশন ব্যবহার করে, কোনও ভাষা এক্সটেনশন প্রয়োজন! (ANSI-সি)
Application আপনার অ্যাপ্লিকেশনটির জন্য সহজ-পাঠযোগ্য উত্স কোড। জিনিসগুলি যতটা সম্ভব সহজ করার জন্য যত্ন নেওয়া হয়েছিল।
ক্লাসের একক উত্তরাধিকার
Interface ইন্টারফেস এবং মিশ্রণগুলি দ্বারা একাধিক উত্তরাধিকার (সংস্করণ 1.3 থেকে)
Ex ব্যতিক্রমগুলি কার্যকর করা হচ্ছে (খাঁটি সিতে!)
ক্লাসের জন্য ভার্চুয়াল ফাংশন
Class সহজ শ্রেণীর প্রয়োগের জন্য বাহ্যিক সরঞ্জাম
আরও তথ্যের জন্য, http://ooc-coding.sourceforge.net/ দেখুন ।
দেখে মনে হচ্ছে লোকে সি ব্যবহার করে সি ++ স্টাইলটি অনুকরণ করছে আমার গ্রহণযোগ্যতা হচ্ছে অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিং সি আসলে স্ট্রাক্ট-ওরিয়েন্টেড প্রোগ্রামিং করছে। তবে আপনি দেরীতে বাইন্ডিং, এনক্যাপসুলেশন এবং উত্তরাধিকারের মতো জিনিসগুলি অর্জন করতে পারেন। উত্তরাধিকারের জন্য আপনি আপনার সাব স্ট্রাক্টের বেস স্ট্রাক্টগুলিতে স্পষ্টভাবে একটি পয়েন্টারকে সংজ্ঞায়িত করেন এবং এটি সম্ভবত একাধিক উত্তরাধিকারের ফর্ম। আপনার যদি তা নির্ধারণ করতে হবে
//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 তৈরির খুব পরিষ্কার উপায়ে ধার দেয়।
সি এর ওওপিতে আরও একটি মোড় নেওয়ার জন্য 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;
}
আমি পার্টিতে কিছুটা দেরি করেছি, তবে আমি এই বিষয়টিতে আমার অভিজ্ঞতাটি ভাগ করে নিতে চাই: আমি এমবেডেড স্টাফ নিয়ে আজকাল কাজ করি, এবং আমার একমাত্র (নির্ভরযোগ্য) সংকলক সি, যাতে আমি অবজেক্ট-ভিত্তিক প্রয়োগ করতে চাই সিটিতে লেখা আমার এম্বেড প্রকল্পগুলিতে যোগাযোগ করুন
আমি এখনও অবধি যে সমাধানগুলি দেখেছি তার বেশিরভাগই টাইপকাস্টগুলি ভারী ব্যবহার করে, তাই আমরা প্রকারের সুরক্ষা হারাব: আপনি যদি ভুল করেন তবে সংকলক আপনাকে সাহায্য করবে না। এটি সম্পূর্ণ অগ্রহণযোগ্য।
আমার যে প্রয়োজনীয়তা রয়েছে:
আমি এই নিবন্ধে আমার পদ্ধতির বিস্তারিত ব্যাখ্যা করেছি: সিতে অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিং ; এছাড়াও, বেস এবং উত্পন্ন ক্লাসগুলির জন্য বয়লারপ্লেট কোডটি অটোজেনারেশনের একটি ইউটিলিটি রয়েছে।
আমি একটি ছোট লাইব্রেরি তৈরি করেছি যেখানে আমি এটি চেষ্টা করেছি এবং আমার কাছে এটি দুর্দান্তভাবে কাজ করে। তাই আমি ভেবেছিলাম অভিজ্ঞতাটি শেয়ার করছি।
https://github.com/thomasfuhringer/oxygen
একক উত্তরাধিকার একটি কাঠামো ব্যবহার করে এবং প্রতিটি অন্যান্য শিশু শ্রেণীর জন্য এটি প্রসারিত করা বেশ সহজেই বাস্তবায়িত হতে পারে। প্যারেন্ট স্ট্রাকচারের একটি সহজ কাস্ট সমস্ত বংশধরদের পিতামাতার পদ্ধতি ব্যবহার করা সম্ভব করে তোলে। যতক্ষণ আপনি জানেন যে কোনও ভেরিয়েবল এই ধরণের একটি অবজেক্টকে ধারণ করে এমন কাঠামোর দিকে নির্দেশ করে আপনি সর্বদা রুট ক্লাসে কাস্ট করতে পারেন এবং অন্তর্মুখি করতে পারেন।
যেমনটি উল্লেখ করা হয়েছে, ভার্চুয়াল পদ্ধতিগুলি কিছুটা কৌশলযুক্ত। তবে তারা করণীয়। জিনিসগুলি সহজ রাখতে আমি কেবল শ্রেণীর বিবরণ কাঠামোতে একটি ক্রিয়াকলাপ ব্যবহার করি যা প্রতিটি শিশু শ্রেণি যেখানে প্রয়োজন হয় স্বতন্ত্র স্লটগুলি অনুলিপি করে এবং পুনরায় তৈরি করে।
একাধিক উত্তরাধিকার বাস্তবায়ন করা বরং জটিল হবে এবং উল্লেখযোগ্য পারফরম্যান্স প্রভাব নিয়ে আসে। সুতরাং আমি এটি ছেড়ে। আমি বাস্তব জীবনের পরিস্থিতিতে পরিষ্কারভাবে মডেল করার জন্য বেশ কয়েকটি ক্ষেত্রে এটি আকাঙ্ক্ষিত এবং দরকারী বলে বিবেচনা করি তবে সম্ভবত 90% ক্ষেত্রে একক উত্তরাধিকারের প্রয়োজনগুলি আবরণ করে। এবং একক উত্তরাধিকার সহজ এবং কোনও মূল্য ব্যয় হয় না।
এছাড়াও আমি টাইপ সুরক্ষা সম্পর্কে যত্ন নেই। আমি মনে করি আপনাকে প্রোগ্রামিং ভুল থেকে রোধ করতে আপনার সংকলকের উপর নির্ভর করা উচিত নয়। এবং এটি আপনাকে কেবল ত্রুটির একটি ছোট অংশ থেকে youাল দেয় sh
সাধারণত কোনও অবজেক্ট ওরিয়েন্টেড পরিবেশে আপনি যথাসম্ভব মেমরি ম্যানেজমেন্টকে স্বয়ংক্রিয় করতে রেফারেন্স গণনা প্রয়োগ করতে চান। সুতরাং আমি "অবজেক্ট" মূল শ্রেণিতে একটি রেফারেন্স গণনাও রেখেছি এবং হিপ মেমরির বরাদ্দ এবং অবলম্বনকে encapsulate করতে কিছু কার্যকারিতা।
এটি সবই খুব সাধারণ এবং দুর্বল এবং সি ++ এর দানবটির সাথে মোকাবিলা করার জন্য আমাকে বাধ্য না করে আমাকে ওওর প্রয়োজনীয় জিনিসগুলি দেয়। এবং আমি সি ল্যান্ডে থাকার নমনীয়তা বজায় রেখেছি, যা অন্যান্য বিষয়ের মধ্যে তৃতীয় পক্ষের লাইব্রেরিগুলিকে সংহত করা সহজ করে তোলে।
আমি অবজেক্টিভ-সি ব্যবহার করার প্রস্তাব দিচ্ছি এটি সি এর সুপারস্টেট is
যদিও উদ্দেশ্য-সি 30 বছরের পুরানো, এটি মার্জিত কোড লেখার অনুমতি দেয়।
হ্যাঁ, তবে আমি কখনও কাউকে সি দিয়ে কোনও ধরণের বহুবর্ষ প্রয়োগ করার চেষ্টা করতে দেখিনি