অবজেক্ট অরিয়েন্টেড সি++ (Class এবং Class Members)

Designed by Freepik

এই লিখাটি পূর্বে আমার ব্যাক্তিগত ব্লগে পাব্লিশ হয়েছে। পড়তে পারবেন এখান থেকে —

সি++ প্রোগ্রামিং এর আসল উদ্দেশ্য হচ্ছে সি প্রোগ্রমিং এর মধ্যে অবজেক্ট অরিয়েন্টেশন যুক্ত করা এবং সি++ এর class গুলো হচ্ছে প্রধান ফিচার যেটার কারনে সি++ অবজেক্ট অরিয়েন্টেশন সাপোর্ট করে।

একটি class এর কাজ হচ্ছে অবজেক্টটি কীভাবে কোন আকার ধারন করবে তা স্পেসিফাই করা এবং এই অবজেক্টটি কীভাবে ডেটা রিপ্রেসেন্ট করবে এবং কোন পদ্ধতি ব্যবহার করে ডেটা ম্যানুপুলেট করবে তা সব ঠিক করে একটা নিট প্যাকেজ তৈরি করা। Class এর ভিতর থাকা ডেটা এবং ফাংশন গুলো কে Member of the Class বলে।

যদিও সি++ এ বিভিন্ন রকমের কয়েকটা ফান্ডামেন্টাল ডেটা টাইপস (int, char, bool, float, double, long etc) আছে কিন্তু সেগুলো ব্যবহার করা হয় খুবই সিম্পল সহজ প্রবলেম সল্ভিং এর জন্য। এগুলো দিয়ে কমপ্লেক্স প্রবলেম সল্ভ করা অনেক কঠিন হয় যায়। সি++ এর class তখন ব্যবহার করা হয় এই সমস্যা গুলো সমাধান করা যায়, কারনে এটা দিয়ে আমরা সমস্যা অনুযায়ী সেটা সল্ভ করার জন্য নিজেদের মতো ডেটা টাইপ ডিফাইন করতে পারি আমরা সি++ এ enumerated types এবং struct ব্যবহার করে কাস্টম ডেটা টাইপ তৈরি করতে পারি। যেমন —

struct DateStruct{
int
year;
int month;
int date;
};

enumerated types এবং struct ডেটা অনলি (যেসকল struct গুলো শুধু ভ্যারিয়েবল কন্টেইন করে) — এরা নন-ট্রেডিশনাল অবজেক্ট অরিয়েন্টেড প্রোগ্রামিং কে রিপ্রেসেন্ট করে, কারন তারা শুধু ডেটা হোল্ড করতে পারে। সি++ ১১ তে নিচের মতোন করে struct তৈরি করে এবং সেটা initialize করা যায় —

DateStruct today {2018, 9, 2};   // use uniform initialization

এখন আমরা যদি ডেটটা প্রিন্ট করতে চাই তাহলে একটা সহজ উপায় হচ্ছে একটি ফাংশন তৈরি করে সেটা করা।

এই প্রোগ্রামটিকে রান করলে এটা ডেট প্রিন্ট করবে।

Prints: 2018/9/2

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

সি++ এ class অনেকটা data-only structs এর মতোন। পার্থক্যটা হচ্ছে class structs থেকে অনেক বেশী পাওয়ারফুল এবং ফ্লেক্সিবিলিটি দিয়ে থাকে।

// struct
struct DateStruct {
int year;
int month;
int day;
};
// class
class DateClass {
public:
int
m_year;
int m_month;
int m_day;
}

উপরের কোডটাতে এক মাত্র এবং সবচেয়ে বড় পার্থক্যটা হচ্ছে public: কীওয়ার্ডটা। এই কীওয়ার্ডটা নিয়ে আমরা বিস্তারিত পরে আলোচনা করবো।

struct এর মতো করেই class ব্যবহার করার জন্য অই class এর ভ্যারিয়েবল টাইপ ডিক্ল্যায়ার করতে হয়।

DateClass today { 2018, 9, 1 };

সি++ ১১ তে আমরা যখন class এর ভ্যারিয়েবল ডিফ্যাইন করি তখন আমরা এটা কে instantiating the class বলি। কারন এই ভ্যারিয়েবলটা তখন নিজেই class এর একটি instance. Class এর একটি ভ্যারিয়েবলকে আবার Object ও বলা হয়। যেভাবে সাধারণ ভাবে ভ্যারিয়েবল ডিফ্যাইন করলে সেটা মেমোরিতে যায়গা দখল করে, সেভাবে একটি অবজেক্টকে instantiating করলে সেটাও অবজেক্টের জন্য মেমোরিতে জায়গা দখল করে।


চলেন এবার কথা বলি মেম্বার ফাংশন (Member Functions) নিয়ে। Class ডেটা হোল্ড করার পাশাপাশি ফাংশনও হোল্ড করতে পারে। তখন সেই ফাংশন কে Class এর Member Functions বলে। Member Functions গুলো কে চাইলে class এর ভেতরে অথবা বাইরে ডিফ্যাইন করা যায়। আমরা এখন class এর ভিতরে মেম্বার ফাংশন ডিফ্যাইন কীভাবে করে সেটা দেখবো।

আমরা ডেট প্রিন্ট করার জন্য এখন মেম্বার ফাংশন ব্যবহার করে একটি class তৈরি করবো।

class DateClass {
public:
int
m_year;
int m_month;
int m_day;
       void print(){   // defines a member function named print()
cout << m_year << "/" << m_month << "/" << m_day;
}
};

পুরো কোডটা —

এই কোডটি রান করলে এটি ডেটটি প্রিন্ট করবে —

prints: 2018/9/2

struct ভার্শন এর কোডটার সাথে আমাদের এই কোডটার অনেক মিল, তাই না?

কিন্তু বেশ কিছু পার্থক্য রয়েছে তারপরেও। যেমন struct ভার্শনে আমরা প্রিন্ট করার জন্য পুরো struct কেই print() ফাংশনের ভিতর প্রথম parameter হিসেবে পাস করে দিয়েছি। নাহলে print() ফাংশন বুঝতো না আমরা কোন DateStruct ব্যবহার করতে চাচ্ছি।

কিন্তু Member Functions একটু অন্যভাবে কাজ করে। আমরা যখন কোডে today.print() কল করলাম তখন আমরা কম্পাইলারকে বলছিলাম এটা যেন DateClass অবজেক্ট থেকে print() মেম্বার ফাংশনকে কল করে। কারন প্রতিটি মেম্বার ফাংশন গুলো অবশ্যই class এর অবজেক্টের সাথে যুক্ত।

চলেন আবার আমাদের print() মেম্বার ফাংশনটিকে দেখি —

void print(){   // defines a member function named print()
cout << m_year << "/" << m_month << "/" << m_day;
}

তো এখানে m_year, m_month, m_day আসলে কাকে রেফার করে? এরা class এর অবজেক্টের সাথে যুক্ত।

আমরা যখন today.print() কল করলাম তখন কম্পাইলারটা m_year কে today.m_year হিসেবে ধরে নেয়, আবার আমরা যখন yesterday.print() কে কল করবো কম্পাইলার তখন m_year কে yesterday.m_year হিসেবে ধরে নিবে। এই সিস্টেমটাকে The Implicit Object বলে। এখানে “m_” দিয়ে আমরা member variables বুঝিয়েছি, ফলে আমরা কোড দেখলে বুঝতে পারবো যে এই ভ্যারিয়েবলটি অন্যান্য সাধারণ অথবা লোকাল ভ্যারিয়েবল থেকে আলাদা।

Member Functions এর ক্ষেত্রে আমরা সবসময় ধরে নেই যে আমাদের Implicit Object ডেটা রয়েছে যেটা নিয়ে class কাজ করতে পারবে যেকোনো সময়। কিন্তু Non Member Functions এর সময় আলাদা ভাবে ডেটা পাস করতে হয়।

সুবিধার জন্য আমরা সবসময় class এর নাম লিখার সময় প্রথম অক্ষরটা বড় হাতের অক্ষর ব্যবহার করি। এটা বেষ্ট প্র্যাকটিস।

বুঝার জন্য আরেকটি class প্রোগ্রাম দিলাম নিচে —

আউটপুট —

মেম্বার ফাংশন সিস্টেমে সবচেয়ে মজার ব্যাপার হচ্ছে, অন্যান্য নরমাল ফাংশনের মতোন এখানে কোনো প্রকার অর্ডার ম্যান্টেইন করে ফাংশন ডিফ্যাইন করতে হয় না। যখন যেখানে ইচ্ছা সেখানেই মেম্বার ফাংশন ডিফাইন করা যায়।


আজকে এই পর্যন্তই। ধন্যবাদ সাথে থাকার জন্য।

#হ্যাপি_প্রোগ্রামিং


আমার ব্যাক্তিগত ব্লগ —

বাংলা ভার্শন — https://with.dibakar.me/

ইংলিশ ভার্শন — https://with.dibakar.me/en/

আমাকে পাবেন —

ফেসবুকে — https://www.facebook.com/dipu.dibakar

টুইটারে — https://twitter.com/iamdibakardipu

ইনস্টাগ্রামে — https://www.instagram.com/dibakardipu/

গিটহাবে — https://github.com/dibakarsutradhar

লিঙ্কড ইনে — https://linkedin.com/in/dibakardipu/