স্ট্যাটিক কীওয়ার্ড এবং সি ++ এর বিভিন্ন ব্যবহার


195

মূলশব্দটি staticহ'ল সি ++ এর বেশ কয়েকটি অর্থ যা আমি খুব বিভ্রান্তিকর মনে করি এবং এটির কীভাবে কাজ করা উচিত তা আমি কখনই আমার মনকে বাঁকতে পারি না।

আমি যা বুঝতে পেরেছি সেখান থেকে staticস্টোরেজ সময়কাল, যার অর্থ এটি বিশ্বব্যাপী ক্ষেত্রে প্রোগ্রামের আজীবন স্থায়ী হয়, তবে আপনি যখন কোনও স্থানীয় সম্পর্কে কথা বলছেন, তার অর্থ এটি ডিফল্টরূপে শূন্য।

সি ++ স্ট্যান্ডার্ড কীওয়ার্ড সহ শ্রেণি ডেটা সদস্যদের জন্য এটি বলে static:

৩.7.১ স্ট্যাটিক স্টোরেজ সময়কাল [বেসিক.স্টি.স্ট্যাটিক]

3 স্ট্যাটিক স্টোরেজ সময়কাল সহ স্থানীয় ভেরিয়েবল ঘোষণার জন্য স্ট্যাটিক কীওয়ার্ড ব্যবহার করা যেতে পারে।

4 শ্রেণীর সংজ্ঞায় শ্রেণীর ডেটা সদস্যকে প্রয়োগ করা মূলশব্দ স্ট্যাটিক ডেটা সদস্যকে স্ট্যাটিক স্টোরেজ সময়কাল দেয়।

স্থানীয় পরিবর্তনশীল এর অর্থ কী ? এটি কি একটি ফাংশন স্থানীয় পরিবর্তনশীল? কারণ সেখানে যখন আপনি কোনও ফাংশন স্থানীয়ভাবে ঘোষণা করেন staticযে এটি কেবল একবার শুরু করা হয়েছিল, প্রথমবার এটি এই ফাংশনে প্রবেশ করে।

এটি কেবল ক্লাসের সদস্যদের সাথে স্টোরেজ সময়কাল সম্পর্কে আলোচনা করে, এটি অযৌক্তিক নির্দিষ্ট হওয়ার বিষয়ে কী, এটিও কোনও সংখ্যার সম্পত্তি static? নাকি সেই স্টোরেজ সময়কাল?

এখন কেস staticএবং ফাইল স্কোপ নিয়ে কী হবে? সমস্ত গ্লোবাল ভেরিয়েবলগুলি ডিফল্টরূপে স্থির স্টোরেজ সময়কাল বলে বিবেচিত হয়? নিম্নলিখিত (বিভাগ ৩.7.১ থেকে) এটি সূচিত করে বলে মনে হচ্ছে:

1 সমস্ত পরিবর্তনশীল যার গতিশীল স্টোরেজ সময়কাল নেই, থ্রেড স্টোরেজ সময়কাল নেই এবং স্থানীয় নয় স্থির স্টোরেজ সময়কাল আছে। এই সত্তাগুলির জন্য স্টোরেজ প্রোগ্রামের সময়কালের জন্য স্থায়ী হবে (3.6.2, 3.6.3)

staticকোনও ভেরিয়েবলের সংযোগের সাথে কীভাবে সম্পর্ক রয়েছে?

এই পুরো staticকীওয়ার্ডটি সরল বিভ্রান্তিকর, কেউ কি এর ইংরেজির বিভিন্ন ব্যবহারগুলি স্পষ্ট করে বলতে পারে এবং ক্লাস সদস্যকে কখন আরম্ভ করতে হবে তাও আমাকে বলতে পারে static?


উত্তর:


147

ভেরিয়েবল:

staticঅনুবাদ ইউনিট যে এর মধ্যে সংজ্ঞায়িত হয়েছে এর "আজীবন" জন্য পরিবর্তনশীল বিদ্যমান এবং:

  • যদি এটি কোনও নেমস্পেসের সুযোগে থাকে (যেমন ফাংশন এবং শ্রেণীর বাইরে), তবে এটি অন্য কোনও অনুবাদ ইউনিট থেকে অ্যাক্সেস করা যাবে না। এটি "অভ্যন্তরীণ লিঙ্কেজ" বা "স্ট্যাটিক স্টোরেজ সময়কাল" হিসাবে পরিচিত। (এটি ব্যতীত শিরোনামগুলিতে করবেন না constexprthing অন্য কিছু, এবং আপনি প্রতিটি অনুবাদ ইউনিটে একটি পৃথক ভেরিয়েবলের সমাপ্তি করুন যা পাগল বিভ্রান্তিকর)
  • যদি এটি কোনও ফাংশনে ভেরিয়েবল হয় তবে অন্য স্থানীয় ভেরিয়েবলের মতো ফাংশনের বাইরে থেকেও এটি অ্যাক্সেস করা যায় না। (এটি তারা উল্লেখ করেছেন স্থানীয়)
  • শ্রেণীর সদস্যদের কারণে কোনও সীমাবদ্ধ সুযোগ নেই static, তবে ক্লাস থেকে সম্বোধন করার পাশাপাশি একটি উদাহরণ (যেমন std::string::npos) দেওয়া যেতে পারে। [দ্রষ্টব্য: আপনি একটি শ্রেণিতে স্থির সদস্য ঘোষণা করতে পারেন , তবে তাদের সাধারণত অনুবাদ ইউনিটে (সিপিপি ফাইল) সংজ্ঞায়িত করা উচিত , এবং যেমন, প্রতি ক্লাসে কেবল একজনই রয়েছে]

কোড হিসাবে অবস্থানগুলি:

static std::string namespaceScope = "Hello";
void foo() {
    static std::string functionScope= "World";
}
struct A {
   static std::string classScope = "!";
};

কোনও অনুবাদ ইউনিটে কোনও ক্রিয়াকলাপ সম্পাদন হওয়ার আগে (সম্ভবত mainসম্পাদন শুরুর পরে ), অনুবাদ ইউনিটে স্থির স্টোরেজ সময়কাল (নেমস্পেস স্কোপ) সহ ভেরিয়েবলগুলি "ধ্রুবক আরম্ভ" ( constexprযেখানে সম্ভব, বা অন্যথায় শূন্য) হবে এবং তারপরে অ- স্থানীয়দের "পরিবর্তনশীল সক্রিয়া" হয় সঠিকভাবে অর্ডার তারা অনুবাদ ইউনিটে সংজ্ঞায়িত করা হয় মধ্যে (জিনিসের জন্য মত std::string="HI";যে নও constexpr)। অবশেষে, ফাংশন-স্থানীয় পরিসংখ্যানগুলি প্রথমবার কার্যকর করা লাইনে "পৌঁছন" করা হয় যেখানে তারা ঘোষণা করা হয়। সমস্ত staticভেরিয়েবলগুলি আরম্ভের বিপরীত ক্রমে ধ্বংস হয়।

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

T& get_global() {
    static T global = initial_value();
    return global;
}

সতর্কতা অবলম্বন করুন, কারণ যখন অনুচ্ছেদটি বলছে যে নামস্পেস-স্কোপ ভেরিয়েবলের ডিফল্টরূপে "স্ট্যাটিক স্টোরেজ সময়কাল" থাকে, তারা "অনুবাদ ইউনিটের আজীবন" বিটকে বোঝায় , তবে এর অর্থ এই নয় যে এটি ফাইলের বাইরে অ্যাক্সেস করা যাবে না।

ক্রিয়াকলাপ

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

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

struct A {
    A() {++A_count;}
    A(const A&) {++A_count;}
    A(A&&) {++A_count;}
    ~A() {--A_count;}

    static int get_count() {return A_count;}
private:
    static int A_count;
}

int main() {
    A var;

    int c0 = var.get_count(); //some compilers give a warning, but it's ok.
    int c1 = A::get_count(); //normal way
}

একটি staticফ্রি-ফাংশন মানে ফাংশনটি অন্য কোনও অনুবাদ ইউনিট দ্বারা উল্লেখ করা হবে না এবং সুতরাং লিঙ্কারটি এটিকে পুরোপুরি উপেক্ষা করতে পারে। এর কয়েকটি সংখ্যক উদ্দেশ্য রয়েছে:

  • কোনও সিপিপি ফাইলে এই গ্যারান্টিটি ব্যবহার করা যায় যে ফাংশনটি অন্য কোনও ফাইল থেকে কখনই ব্যবহৃত হয় না।
  • একটি শিরোলেখ স্থাপন করা যেতে পারে এবং প্রতিটি ফাইলের নিজস্ব ফাংশনটির অনুলিপি থাকবে। কার্যকর নয়, যেহেতু ইনলাইন একই জিনিসটি বেশ কার্যকর করে।
  • কাজ হ্রাস করে লিংক সময়ের গতি বাড়ায়
  • প্রতিটি অনুবাদ ইউনিটে একই নামের সাথে একটি ফাংশন রাখতে পারে এবং তারা সকলে বিভিন্ন জিনিস করতে পারে। উদাহরণস্বরূপ, আপনি static void log(const char*) {}প্রতিটি সিপিপি ফাইলে একটি রাখতে পারেন এবং তারা প্রত্যেকে আলাদাভাবে লগ করতে পারে।

1
শ্রেণীর সদস্যদের কী হবে? এটি কি তৃতীয় পৃথক মামলা নয়?
entienne

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

1
@ লুচিয়ানগ্রিগোর: আপনার বক্তব্যটি দেখার সময় আমি কোন শব্দটি ব্যবহার করব তা নিশ্চিত নই।
হাঁসকে

1
@ স্টিভ 314: আপনি কী বলতে চাইছেন তা আমি বুঝতে পেরেছি, তবে স্থির হিসাবে এত ভয়াবহ ওভারলোড হওয়া শব্দটির সাথে কথা বলার সময় আমি আশা করি আমরা সবাই আরও কিছুটা সাবধান থাকি। বিশেষত সমস্ত গ্লোবাল (সত্যই নেমস্পেস লেভেল) ভেরিয়েবলের স্থির সময়কাল থাকে তাই স্ট্যাটিক গ্লোবাল ভেরিয়েবলগুলিতে স্ট্যাটিক যুক্ত হিসাবে বোঝা যায় namespace A { static int x; }, যার অর্থ অভ্যন্তরীণ সংযোগ এবং স্থির শ্রেণীর ডেটা সদস্যদের আচরণ থেকে খুব আলাদা ।
ডেভিড রদ্রিগেজ - ড্রিবিস

1
"যদি এটি কোনও নেমস্পেসের সুযোগে থাকে, তবে অন্য কোনও অনুবাদ ইউনিট থেকে এটি অ্যাক্সেস করা যায় না ..." যদি এটি নামস্থান সুযোগে থাকে তবে আপনার অর্থ কী? এটা কি সবসময় হয় না, আপনি কি উদাহরণ এবং পাল্টা উদাহরণ দিতে পারেন?
আতুরস্যামস

66

স্ট্যাটিক স্টোরেজ সময়কাল মানে প্রোগ্রামের আজীবন চলাকালীন চলক স্মৃতিতে একই জায়গায় থাকে।

লিঙ্কেজ এটির জন্য অরথোগোনাল।

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

কীওয়ার্ডটি staticঅভ্যন্তরীণ সংযোগ এবং স্থিতিশীল স্টোরেজ বোঝাতে ব্যবহৃত হতে পারে তবে সংক্ষেপে এগুলি পৃথক।

স্থানীয় পরিবর্তনশীল এর অর্থ কী? এটি কি একটি ফাংশন স্থানীয় পরিবর্তনশীল?

হ্যাঁ. ভেরিয়েবলটি কখন আরম্ভ করা হবে তা বিবেচনা না করেই (ফাংশনটিতে প্রথম কল করার সময় এবং যখন কার্যকর করার পথটি ঘোষণার পয়েন্টে পৌঁছায়), প্রোগ্রামের জীবনের স্মৃতিতে এটি একই জায়গায় থাকবে res এই ক্ষেত্রে, staticএটি স্ট্যাটিক স্টোরেজ দেয়।

এখন স্ট্যাটিক এবং ফাইল স্কোপ নিয়ে কেস কী হবে? সমস্ত গ্লোবাল ভেরিয়েবলগুলি ডিফল্টরূপে স্থির স্টোরেজ সময়কাল বলে বিবেচিত হয়?

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

স্থির একটি চলক সংযোগের সাথে কীভাবে সম্পর্কযুক্ত?

এটি নেমস্পেস-স্কোপড ভেরিয়েবলগুলিকে অভ্যন্তরীণ লিঙ্কেজ দেয়। এটি সদস্য এবং স্থানীয় ভেরিয়েবলগুলি স্থিতিশীল স্টোরেজ সময়কাল দেয়।

আসুন এই সমস্ত উপর প্রসারিত করুন:

//

static int x; //internal linkage
              //non-static storage - each translation unit will have its own copy of x
              //NOT A TRUE GLOBAL!

int y;        //static storage duration (can be used with extern)
              //actual global
              //external linkage
struct X
{
   static int x;     //static storage duration - shared between class instances 
};

void foo()
{
   static int x;     //static storage duration - shared between calls
}

এই সম্পূর্ণ স্ট্যাটিক কীওয়ার্ডটি সরল বিভ্রান্তিকর

অবশ্যই আপনি এটির সাথে পরিচিত না হলে। :) ভাষায় নতুন কীওয়ার্ড যুক্ত এড়ানোর চেষ্টা করে, কমিটি এইটিকে আবার ব্যবহার করেছে, আইএমও - বিভ্রান্তি। এটি বিভিন্ন জিনিসকে বোঝাতে ব্যবহৃত হয় (আমি বলতে পারি, সম্ভবত বিরোধী জিনিস)।


1
আমাকে এটি সোজা পেতে দাও - আপনি বলছেন যে যখন আমি static int xনাম স্থানের সুযোগে বলি , এটি এটি স্ট্যাটাসহীন স্টোরেজ দেয়?
মাইকেল হাগার

29

প্রশ্নটি পরিষ্কার করার জন্য, আমি বরং 'স্ট্যাটিক' কীওয়ার্ডের ব্যবহারটি তিনটি পৃথক আকারে শ্রেণিবদ্ধ করব:

(ক)। ভেরিয়েবল

(বি)। ক্রিয়াকলাপ

(গ)। সদস্যের ভেরিয়েবল / ক্লাসের কার্যাদি

ব্যাখ্যা সাব-শিরোনামগুলির প্রতিটিের জন্য নীচে অনুসরণ করে:

(ক) ভেরিয়েবলের জন্য 'স্ট্যাটিক' কীওয়ার্ড

তবে এটি সঠিকভাবে ব্যাখ্যা করা এবং বোঝা গেলে এটি সামান্য কৌশলযুক্ত হতে পারে pretty

এটি ব্যাখ্যা করার জন্য, প্রথমে ভেরিয়েবলের সুযোগ, সময়কাল এবং লিঙ্কেজ সম্পর্কে জেনে রাখা সত্যিই দরকারী , যা না করে স্থায়ী কীওয়ার্ডের নীরব ধারণার মাধ্যমে জিনিসগুলি দেখতে সবসময় কঠিন

1. সুযোগ : ফাইলটিতে কোথায়, ভেরিয়েবল অ্যাক্সেসযোগ্য তা নির্ধারণ করে। এটি দুটি ধরণের হতে পারে: (i) স্থানীয় বা ব্লক স্কোপ । (ii) গ্লোবাল স্কোপ

২. সময়কাল : কোনও ভেরিয়েবল তৈরি ও ধ্বংস হওয়ার পরে তা নির্ধারণ করে। আবার এটি দুটি ধরণের: (i) স্বয়ংক্রিয় স্টোরেজ সময়কাল (স্থানীয় বা ব্লক স্কোপযুক্ত ভেরিয়েবলগুলির জন্য)। (ii) স্ট্যাটিক স্টোরেজ সময়কাল ( স্থির স্পেসিফায়ার সহ গ্লোবাল স্কোপ বা স্থানীয় ভেরিয়েবল (কোনও ফাংশন বা একটি কোড ব্লকের একটি ভেরিয়েবলগুলির জন্য ) for

৩. লিঙ্কেজ : নির্ধারণ করে যে কোনও ফাইলের কোনও ভেরিয়েবল অ্যাক্সেস করা যায় (বা লিঙ্ক করা)) আবার (এবং ভাগ্যক্রমে) এটি দুটি ধরণের: (i) অভ্যন্তরীণ লিঙ্কেজ (ব্লক স্কোপ এবং গ্লোবাল স্কোপ / ফাইল স্কোপ / গ্লোবাল নেমস্পেস স্কোপযুক্ত ভেরিয়েবলগুলির জন্য ) (ii) বহিরাগত লিঙ্কেজ (কেবল গ্লোবাল স্কোপ / ফাইল স্কোপ / এর জন্য থাকা ভেরিয়েবলগুলির জন্য ) গ্লোবাল নেমস্পেস স্কোপ)

সরল গ্লোবাল এবং স্থানীয় ভেরিয়েবলগুলি (স্ট্যাটিক স্টোরেজ সময়কাল সহ কোনও স্থানীয় ভেরিয়েবল নেই) সম্পর্কে আরও ভাল করে বোঝার জন্য নীচে একটি উদাহরণ উল্লেখ করুন:

//main file
#include <iostream>

int global_var1; //has global scope
const global_var2(1.618); //has global scope

int main()
{
//these variables are local to the block main.
//they have automatic duration, i.e, they are created when the main() is 
//  executed and destroyed, when main goes out of scope
 int local_var1(23);
 const double local_var2(3.14);

 {
/* this is yet another block, all variables declared within this block are 
 have local scope limited within this block. */
// all variables declared within this block too have automatic duration, i.e, 
/*they are created at the point of definition within this block,
 and destroyed as soon as this block ends */
   char block_char1;
   int local_var1(32) //NOTE: this has been re-declared within the block, 
//it shadows the local_var1 declared outside

 std::cout << local_var1 <<"\n"; //prints 32

  }//end of block
  //local_var1 declared inside goes out of scope

 std::cout << local_var1 << "\n"; //prints 23

 global_var1 = 29; //global_var1 has been declared outside main (global scope)
 std::cout << global_var1 << "\n"; //prints 29
 std::cout << global_var2 << "\n"; //prints 1.618

 return 0;
}  //local_var1, local_var2 go out of scope as main ends
//global_var1, global_var2 go out of scope as the program terminates 
//(in this case program ends with end of main, so both local and global
//variable go out of scope together

লিংকেজের ধারণাটি এখন আসে। যখন একটি ফাইলে সংজ্ঞায়িত গ্লোবাল ভেরিয়েবলটি অন্য ফাইলে ব্যবহারের উদ্দেশ্যে হয়, তখন ভেরিয়েবলের লিঙ্কেজ একটি গুরুত্বপূর্ণ ভূমিকা পালন করে।

গ্লোবাল ভেরিয়েবলের লিংকেজ কীওয়ার্ডগুলি দ্বারা নির্দিষ্ট করা হয়: (i) স্থির এবং, (ii) বাহ্যিক

(এখন আপনি ব্যাখ্যা পেতে)

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

1. বিশ্বব্যাপী সুযোগ সহ ভেরিয়েবলের জন্য স্ট্যাটিক কীওয়ার্ড

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

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

বিপরীতে, গ্লোবাল ভেরিয়েবলের যদি স্থির কীওয়ার্ড থাকে, তবে এটির বাইরে এটি ঘোষিত কোনও ফাইলে ব্যবহার করা যাবে না।

(স্পষ্টকরণের জন্য নীচে উদাহরণ দেখুন)

উদাহরণ:

//main2.cpp
 static int global_var3 = 23;  /*static global variable, cannot be                            
                                accessed in anyother file */
 extern double global_var4 = 71; /*can be accessed outside this file                  linked to main2.cpp */
 int main() { return 0; }

main3.cpp

//main3.cpp
#include <iostream>

int main()
{
   extern int gloabl_var4; /*this variable refers to the gloabal_var4
                            defined in the main2.cpp file */
  std::cout << global_var4 << "\n"; //prints 71;

  return 0;
}

এখন সি ++ তে যে কোনও চলক হয় কনস্ট বা একটি কনস্ট-কনস্ট্যান্ট হতে পারে এবং প্রতিটি 'কনস্ট-নেস' এর জন্য আমরা ডিফল্ট সি ++ লিঙ্কেজের দুটি ক্ষেত্রে পাই, যদি কোনওটি নির্দিষ্ট না হয়:

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

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

বিভিন্ন লিঙ্কেজ সহ বিশ্বব্যাপী স্কোপ ভেরিয়েবলের সংক্ষিপ্তসার এখানে

//globalVariables1.cpp 

// defining uninitialized vairbles
int globalVar1; //  uninitialized global variable with external linkage 
static int globalVar2; // uninitialized global variable with internal linkage
const int globalVar3; // error, since const variables must be initialized upon declaration
const int globalVar4 = 23; //correct, but with static linkage (cannot be accessed outside the file where it has been declared*/
extern const double globalVar5 = 1.57; //this const variable ca be accessed outside the file where it has been declared

পরবর্তী আমরা অনুসন্ধান করি যে উপরের গ্লোবাল ভেরিয়েবলগুলি যখন অন্য কোনও ফাইলে অ্যাক্সেস করা হয় তখন কীভাবে আচরণ করে।

//using_globalVariables1.cpp (eg for the usage of global variables above)

// Forward declaration via extern keyword:
 extern int globalVar1; // correct since globalVar1 is not a const or static
 extern int globalVar2; //incorrect since globalVar2 has internal linkage
 extern const int globalVar4; /* incorrect since globalVar4 has no extern 
                         specifier, limited to internal linkage by
                         default (static specifier for const variables) */
 extern const double globalVar5; /*correct since in the previous file, it 
                           has extern specifier, no need to initialize the
                       const variable here, since it has already been
                       legitimately defined perviously */

2. স্থানীয় স্কোপ সহ ভেরিয়েবলের জন্য স্ট্যাটিক কীওয়ার্ড

স্থানীয় স্কোপে ভেরিয়েবলের জন্য স্ট্যাটিক কীওয়ার্ডের উপর আপডেটগুলি (আগস্ট 2019)

এটি আরও দুটি বিভাগে বিভক্ত করা যেতে পারে:

(i) একটি ফাংশন ব্লকের মধ্যে ভেরিয়েবলের জন্য স্ট্যাটিক কীওয়ার্ড এবং (ii) নামবিহীন স্থানীয় ব্লকের মধ্যে ভেরিয়েবলের জন্য স্ট্যাটিক কীওয়ার্ড।

(i) একটি ফাংশন ব্লকের মধ্যে চলকগুলির জন্য স্থিতিশীল কীওয়ার্ড।

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

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

একটি উদাহরণ দেখুন।

//localVarDemo1.cpp    
 int localNextID()
{
  int tempID = 1;  //tempID created here
  return tempID++; //copy of tempID returned and tempID incremented to 2
} //tempID destroyed here, hence value of tempID lost

int newNextID()
{
  static int newID = 0;//newID has static duration, with internal linkage
  return newID++; //copy of newID returned and newID incremented by 1
}  //newID doesn't get destroyed here :-)


int main()
{
  int employeeID1 = localNextID();  //employeeID1 = 1
  int employeeID2 = localNextID();  // employeeID2 = 1 again (not desired)
  int employeeID3 = newNextID(); //employeeID3 = 0;
  int employeeID4 = newNextID(); //employeeID4 = 1;
  int employeeID5 = newNextID(); //employeeID5 = 2;
  return 0;
}

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

//localVarDemo2.cpp 

//static storage duration with global scope 
//note this variable can be accessed from outside the file
//in a different compilation unit by using `extern` specifier
//which might not be desirable for certain use case.
static int globalId = 0;

int newNextID()
{
  static int newID = 0;//newID has static duration, with internal linkage
  return newID++; //copy of newID returned and newID incremented by 1
}  //newID doesn't get destroyed here


int main()
{
    //since globalId is accessible we use it directly
  const int globalEmployee1Id = globalId++; //globalEmployeeId1 = 0;
  const int globalEmployee2Id = globalId++; //globalEmployeeId1 = 1;

  //const int employeeID1 = newID++; //this will lead to compilation error since newID++ is not accessible direcly. 
  int employeeID2 = newNextID(); //employeeID3 = 0;
  int employeeID2 = newNextID(); //employeeID3 = 1;

  return 0;
}

স্থির গ্লোবাল এবং স্ট্যাটিক স্থানীয় ভেরিয়েবলের পছন্দ সম্পর্কে আরও ব্যাখ্যা এই স্ট্যাকওভারফ্লো থ্রেডে পাওয়া যেতে পারে

(ii) নামবিহীন স্থানীয় ব্লকের মধ্যে ভেরিয়েবলের স্থিতিশীল কীওয়ার্ড।

লোকাল ব্লকের মধ্যে স্ট্যাটিক ভেরিয়েবল (কোনও ফাংশন ব্লক নয়) একবার ব্লকের বাইরে স্থানীয় ব্লকের সুযোগ ছাড়াই যায় না। এই নিয়মের কোনও সতর্কতা নেই।

    //localVarDemo3.cpp 
    int main()
    {

      {
          const static int static_local_scoped_variable {99};
      }//static_local_scoped_variable goes out of scope

      //the line below causes compilation error
      //do_something is an arbitrary function
      do_something(static_local_scoped_variable);
      return 0;
    }

সি ++ 11 এমন কীওয়ার্ডটি চালু করেছিল constexprযা সংকলন সময়ে একটি অভিব্যক্তির মূল্যায়নের গ্যারান্টি দেয় এবং সংকলককে কোডটি অনুকূলিতকরণের অনুমতি দেয়। এখন যদি কোনও সুযোগের মধ্যে একটি স্ট্যাটিক কনস্ট ভেরিয়েবলের মানটি সংকলন সময়ে জানা যায়, কোডটি তার সাথে অনুরূপ পদ্ধতিতে অনুকূলিত হয় constexprএখানে একটি ছোট উদাহরণ

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

বি। 'স্ট্যাটিক' ফাংশনের জন্য ব্যবহৃত কীওয়ার্ড

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

ফাংশন ঘোষণার আগে একটি স্ট্যাটিক কীওয়ার্ড ব্যবহার করে এর সংযোগটি অভ্যন্তরের সাথে সীমাবদ্ধ করে , অর্থাত্ একটি সংবিধানের বাইরে কোনও ফাইলের মধ্যে একটি স্ট্যাটিক ফাংশন ব্যবহার করা যায় না।

সি স্টাইট কীওয়ার্ড ক্লাসের সদস্য ভেরিয়েবল এবং ফাংশনের জন্য ব্যবহৃত হয়

ক্লাসের সদস্য ভেরিয়েবলের জন্য 'স্ট্যাটিক' কীওয়ার্ড

আমি এখানে একটি উদাহরণ দিয়ে সরাসরি শুরু

#include <iostream>

class DesignNumber
{
  private:

      static int m_designNum;  //design number
      int m_iteration;     // number of iterations performed for the design

  public:
    DesignNumber() {     }  //default constructor

   int  getItrNum() //get the iteration number of design
   {
      m_iteration = m_designNum++;
      return m_iteration;
   }
     static int m_anyNumber;  //public static variable
};
int DesignNumber::m_designNum = 0; // starting with design id = 0
                     // note : no need of static keyword here
                     //causes compiler error if static keyword used
int DesignNumber::m_anyNumber = 99; /* initialization of inclass public 
                                    static member  */
enter code here

int main()
{
   DesignNumber firstDesign, secondDesign, thirdDesign;
   std::cout << firstDesign.getItrNum() << "\n";  //prints 0
   std::cout << secondDesign.getItrNum() << "\n"; //prints 1
   std::cout << thirdDesign.getItrNum() << "\n";  //prints 2

   std::cout << DesignNumber::m_anyNumber++ << "\n";  /* no object
                                        associated with m_anyNumber */
   std::cout << DesignNumber::m_anyNumber++ << "\n"; //prints 100
   std::cout << DesignNumber::m_anyNumber++ << "\n"; //prints 101

   return 0;
}

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

অন্যান্য সদস্য ভেরিয়েবলগুলির মতো, কোনও শ্রেণীর স্থির সদস্য ভেরিয়েবলগুলি কোনও শ্রেণীর অবজেক্টের সাথে সম্পর্কিত নয়, যা মূল ফাংশনে যে কোনও নাম্বার মুদ্রণ দ্বারা প্রদর্শিত হয়

কনস্ট বনাম ক্লাসে নন-কনস্টের স্ট্যাটিক সদস্য ভেরিয়েবল

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

(২) ক্লাসের const স্ট্যাটিক সদস্য ভেরিয়েবল এই সহজবোধ্য এবং অন্যান্য const সদস্য পরিবর্তনশীল আরম্ভের এর কনভেনশন সঙ্গে যায়, একটি ক্লাসের অর্থাত const স্ট্যাটিক সদস্য ভেরিয়েবল যাবে ঘোষণার সময়ে সক্রিয়া এবং তারা শেষে সক্রিয়া করা যেতে পারে শ্রেণীর সংজ্ঞার পরে ক্লাসের ঘোষণার যে শ্রেণিবদ্ধকরণের পরে আরম্ভ করার সময় মূল শব্দটি কনট স্ট্যাটিক সদস্যের সাথে যুক্ত করা দরকার with

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

ক্লাসে স্ট্যাটিক সদস্য ভেরিয়েবলের আরও উদাহরণের জন্য শিখুন নীচের লিঙ্কটি শিখুন http://www.learncpp.com/cpp-tutorial/811-static-member-variables/

২. ক্লাসের সদস্য ফাংশনের জন্য 'স্ট্যাটিক' কীওয়ার্ড

ক্লাসের সদস্য ভেরিয়েবলগুলি যেমন স্থির হতে পারে, তেমনি ক্লাসগুলির সদস্য ফাংশনও হতে পারে। ক্লাসগুলির সাধারণ সদস্য ফাংশন সর্বদা শ্রেণীর ধরণের কোনও বিষয়ের সাথে যুক্ত থাকে। বিপরীতে, কোনও শ্রেণীর স্থির সদস্যের কার্যগুলি শ্রেণীর কোনও বস্তুর সাথে সম্পর্কিত নয়, অর্থাত্ তাদের এই পয়েন্টার নেই * *

দ্বিতীয়ত যেহেতু শ্রেণীর স্থির সদস্য ফাংশনগুলির এই পয়েন্টার নেই *, সুতরাং প্রধান ফাংশনে ক্লাসের নাম এবং স্কোপ রেজোলিউশন অপারেটর ব্যবহার করে তাদের বলা যেতে পারে (ClassName :: ফাংশননেম ();)

তৃতীয়ত কোনও শ্রেণীর স্থির সদস্যের ক্রিয়াকলাপ কেবল শ্রেণীর স্থির সদস্য ভেরিয়েবলগুলি অ্যাক্সেস করতে পারে, যেহেতু একটি শ্রেণীর অ স্থিতিশীল সদস্য ভেরিয়েবলগুলি কোনও শ্রেণীর অবজেক্টের অন্তর্ভুক্ত থাকতে হবে।

ক্লাসে স্ট্যাটিক সদস্য ফাংশন সম্পর্কিত আরও উদাহরণের জন্য learnncpp.com থেকে নিম্নলিখিত লিঙ্কটি সন্ধান করুন

http://www.learncpp.com/cpp-tutorial/812-static-member-functions/


1
1) সি ++ 17 এর আগে কেবল অবিচ্ছেদ্য স্ট্যাটিক কনস্ট মেম্বার ভেরিয়েবলগুলি ইন-ক্লাস ইনিশিয়াল করা যেতে পারে, উদাহরণস্বরূপ struct Foo{static const std::string name = "cpp";};ত্রুটি, nameশ্রেণীর বাইরে সংজ্ঞা দিতে হবে; সি ++ ১ 17 এ প্রবেশ করানো ইনলাইন ভেরিয়েবলগুলির সাথে একটি কোড করতে পারে: struct Foo{static inline const std::string name = "cpp";};২) সার্বজনীন স্থিতিশীল সদস্য / সদস্য ফাংশনগুলি স্কোপ রেজোলিউশন অপারেটরের সাথে শ্রেণীর নাম এবং ডট অপারেটরের উদাহরণ
সহও পাওয়া যায়

"M_anyVariable" "m_anyNumber" হওয়া উচিত নয়? আপনার শেষ কোড উদাহরণে?
gebbissimo

আমি উত্তরের সম্পূর্ণতা এবং সঠিকতা বিচার করতে পারি না, তবে এটি সত্যই বিস্তৃত বলে মনে হচ্ছে এবং এটি অনুসরণ করা সহজ। অনেক ধন্যবাদ! আপনি যদি এটি উন্নতি করতে চেয়েছিলেন তবে শুরুতে একটি সংক্ষিপ্ত সংক্ষিপ্তসার উপকারী হতে পারে কারণ এটি বেশ দীর্ঘ পাঠ্য এবং মূল পয়েন্টগুলি খুব সহজেই "অভ্যন্তরীণ / বাহ্যিক" এর মতো পদগুলি জানেন এমন লোকদের জন্য নেস্টেড তালিকা বা গাছের ডায়াগ্রাম হিসাবে সহজেই দৃশ্যমান হতে পারে লিঙ্কেজ "
gebbissimo

18

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

int myFun()
{
static int i=5;
i++;
return i;
}
int main()
{
printf("%d", myFun());
printf("%d", myFun());
printf("%d", myFun());
}

678পরিবর্তে প্রদর্শিত হবে 666, কারণ এটি বর্ধিত মান মনে রাখে।

স্থির সদস্য হিসাবে, তারা শ্রেণীর উদাহরণগুলিতে তাদের মান সংরক্ষণ করে। সুতরাং নিম্নলিখিত কোড:

struct A
{
static int a;
};
int main()
{
A first;
A second;
first.a = 3;
second.a = 4;
printf("%d", first.a);
}

4 টি মুদ্রণ করবে, কারণ প্রথম.a এবং দ্বিতীয়.a মূলত একই ভেরিয়েবল। সূচনা হিসাবে, এই প্রশ্নটি দেখুন।


এটি নেমস্পেস স্কোপ ভেরিয়েবলগুলিকে সম্বোধন করে না।
মাইকেল হাগার

10

আপনি যখন staticফাইল স্কোপে কোনও ভেরিয়েবল ঘোষণা করেন, তখন সেই পরিবর্তনশীলটি কেবলমাত্র সেই নির্দিষ্ট ফাইলে পাওয়া যায় (প্রযুক্তিগতভাবে, * অনুবাদ ইউনিট, তবে আসুন এটি খুব জটিল করে তুলবেন না)। উদাহরণ স্বরূপ:

a.cpp

static int x = 7;

void printax()
{
    cout << "from a.cpp: x=" << x << endl;
}

b.cpp

static int x = 9;

void printbx()
{
    cout << "from b.cpp: x=" << x << endl;
}

main.cpp:

int main(int, char **)
{
    printax(); // Will print 7
    printbx(); // Will print 9

    return 0;
}

একটি জন্য স্থানীয় পরিবর্তনশীল, staticমানে যে পরিবর্তনশীল শূন্য সক্রিয়া হতে হবে এবং কলের মধ্যে এর মান বজায় রাখা:

unsigned int powersoftwo()
{
    static unsigned lastpow;

    if(lastpow == 0)
        lastpow = 1;
    else
        lastpow *= 2;

    return lastpow;
}

int main(int, char **)
{
    for(int i = 0; i != 10; i++)
        cout << "2^" << i << " = " << powersoftwo() << endl;
}

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

class Test
{
private:
    static char *xxx;

public:
    static int yyy;

public:
    Test()
    {        
        cout << this << "The static class variable xxx is at address "
             << static_cast<void *>(xxx) << endl;
        cout << this << "The static class variable yyy is at address "
             << static_cast<void *>(&y) << endl;
    }
};

// Necessary for static class variables.
char *Test::xxx = "I'm Triple X!";
int Test::yyy = 0;

int main(int, char **)
{
    Test t1;
    Test t2;

    Test::yyy = 666;

    Test t3;
};

শ্রেণিহীন ফাংশন হিসাবে চিহ্নিত করা staticফাংশনটিকে কেবল সেই ফাইল থেকে অ্যাক্সেসযোগ্য এবং অন্যান্য ফাইল থেকে অ্যাক্সেসযোগ্য করে তোলে।

a.cpp

static void printfilename()
{ // this is the printfilename from a.cpp - 
  // it can't be accessed from any other file
    cout << "this is a.cpp" << endl;
}

b.cpp

static void printfilename()
{ // this is the printfilename from b.cpp - 
  // it can't be accessed from any other file
    cout << "this is b.cpp" << endl;
}

শ্রেণীর সদস্য ফাংশনগুলির জন্য, তাদের চিহ্নিত করার staticঅর্থ হ'ল ফাংশনটির কোনও নির্দিষ্ট উপাদানের (যেমন এটির কোনও thisপয়েন্টার নেই) কল করার প্রয়োজন নেই।

class Test
{
private:
    static int count;

public:
    static int GetTestCount()
    {
        return count;
    };

    Test()
    {
        cout << this << "Created an instance of Test" << endl;
        count++;
    }

    ~Test()
    {
        cout << this << "Destroyed an instance of Test" << endl;
        count--;
    }
};

int Test::count = 0;

int main(int, char **)
{
    Test *arr[10] = { NULL };

    for(int i = 0; i != 10; i++)
        arr[i] = new Test();

    cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;

    // now, delete them all except the first and last!
    for(int i = 1; i != 9; i++)
        delete arr[i];        

    cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;

    delete arr[0];

    cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;

    delete arr[9];

    cout << "There are " << Test::GetTestCount() << " instances of the Test class!" << endl;

    return 0;
}

8

স্ট্যাটিক ভেরিয়েবলগুলি একটি শ্রেণীর প্রতিটি উদাহরণের মধ্যে ভাগ করা হয়, পরিবর্তে প্রতিটি শ্রেণীর নিজস্ব ভেরিয়েবল থাকে।

class MyClass
{
    public:
    int myVar; 
    static int myStaticVar;
};

//Static member variables must be initialized. Unless you're using C++11, or it's an integer type,
//they have to be defined and initialized outside of the class like this:
MyClass::myStaticVar = 0;

MyClass classA;
MyClass classB;

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

MyClass::myStaticVar //Assuming it's publicly accessible.

যখন কোনও ফাংশনের অভ্যন্তরীণ স্থানীয় ভেরিয়েবল হিসাবে ব্যবহৃত হয় (এবং শ্রেণীর সদস্য-পরিবর্তনশীল হিসাবে নয়) স্থির কীওয়ার্ডটি কিছু আলাদা করে। এটি আপনাকে বিশ্বব্যাপী সুযোগ না দিয়ে স্থির পরিবর্তনশীল তৈরি করতে দেয়।

int myFunc()
{
   int myVar = 0; //Each time the code reaches here, a new variable called 'myVar' is initialized.
   myVar++;

   //Given the above code, this will *always* print '1'.
   std::cout << myVar << std::endl;

   //The first time the code reaches here, 'myStaticVar' is initialized. But ONLY the first time.
   static int myStaticVar = 0;

   //Each time the code reaches here, myStaticVar is incremented.
   myStaticVar++;

   //This will print a continuously incrementing number,
   //each time the function is called. '1', '2', '3', etc...
   std::cout << myStaticVar << std::endl;
}

এটি দৃ pers়তার সাথে বিশ্বব্যাপী পরিবর্তনশীল ... তবে সুযোগ / অ্যাক্সেসযোগ্যতায় বিশ্বব্যাপী না হয়ে।

আপনার স্থির সদস্যের কার্যাদিও থাকতে পারে। স্ট্যাটিক ফাংশনগুলি মূলত অ-সদস্য ফাংশন, তবে শ্রেণীর নামের নামের জায়গার ভিতরে এবং শ্রেণীর সদস্যদের ব্যক্তিগত অ্যাক্সেস সহ।

class MyClass
{
    public:
    int Func()
    {
        //...do something...
    }

    static int StaticFunc()
    {
        //...do something...
    }
};

int main()
{
   MyClass myClassA;
   myClassA.Func(); //Calls 'Func'.
   myClassA.StaticFunc(); //Calls 'StaticFunc'.

   MyClass::StaticFunc(); //Calls 'StaticFunc'.
   MyClass::Func(); //Error: You can't call a non-static member-function without a class instance!

   return 0;
}

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


1
"ধরে নিচ্ছি এটি সর্বজনীনভাবে অ্যাক্সেসযোগ্য" " - না।
লুচিয়ান গ্রিগোর

2
myStaticVarসংজ্ঞায়িত করা প্রয়োজন। কীন্ডার উল্লেখ করা গুরুত্বপূর্ণ যে staticকীওয়ার্ডের শব্দার্থকতা সম্পর্কে কোনও প্রশ্নের উত্তর দেওয়ার সময় , আপনি কি ভাবেন না?
প্রিটোরিয়ান

@ প্রিটোরিয়ান: ধন্যবাদ, স্থির
জামিন গ্রে

1
@ জ্যামিনগ্রি "স্ট্যাটিক স্ট্যান্ডেলোন" দ্বারা আমি স্থির অ-সদস্য ফাংশন বোঝাতে চাই এবং আমি যখনই কেবলমাত্র বর্তমান সিপিপি ফাইলে কিছু নতুন কার্যকারিতা প্রয়োজন তখনই আমি এটি লিখি এবং লিঙ্কারটিকে কোনও অতিরিক্ত প্রতীক প্রক্রিয়াকরণ করতে চাই না।
ভিআরপি

1
@ ভিআর অদ্ভুত! আমি জানতাম না যে কার্যকারিতাটির অস্তিত্ব আছে। আমার জ্ঞানকে প্রশস্ত করার জন্য ধন্যবাদ!
জামিন গ্রে

1

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

class A
{
public:
    A();
    ~A();
    void somePublicMethod();
private:
    void somePrivateMethod();
};

আপনি যখন আপনার মেইনে এই শ্রেণিটি ইনস্ট্যান্ট করেন আপনি এমন কিছু করেন।

int main()
{
   A a1;
   //do something on a1
   A a2;
   //do something on a2
}

এই দুটি শ্রেণীর দৃষ্টান্ত একে অপরের থেকে সম্পূর্ণ আলাদা এবং একে অপরের থেকে স্বতন্ত্রভাবে পরিচালনা করে। তবে আপনি যদি ক্লাস এটিকে পুনরায় তৈরি করতে চান।

class A
{
public:
    A();
    ~A();
    void somePublicMethod();
    static int x;
private:
    void somePrivateMethod();
};

আবার মেইন ফিরে যেতে দিন।

int main()
{
   A a1;
   a1.x = 1;
   //do something on a1
   A a2;
   a2.x++;
   //do something on a2
}

তারপরে a1 এবং a2 ইন্ট x এর একই অনুলিপি ভাগ করবে যার মাধ্যমে এ 1-এ এক্স-এর যে কোনও ক্রিয়াকলাপ সরাসরি এ 2-এ এক্স এর ক্রিয়াকলাপকে প্রভাবিত করবে। আমি যদি এই কাজটি করতাম

int main()
{
   A a1;
   a1.x = 1;
   //do something on a1
   cout << a1.x << endl; //this would be 1
   A a2;
   a2.x++;
   cout << a2.x << endl; //this would be 2 
   //do something on a2
}

ক্লাস এ এর ​​উভয় দৃষ্টান্ত স্ট্যাটিক ভেরিয়েবল এবং ফাংশন ভাগ করে। আশা করি এটি আপনার প্রশ্নের উত্তর দেয়। আমার সি এর সীমিত জ্ঞান আমাকে বলতে দেয় যে কোনও ফাংশন বা ভেরিয়েবলকে স্থির হিসাবে সংজ্ঞায়িত করার অর্থ এটি কেবল ফাইলে দৃশ্যমান যে ফাংশন বা ভেরিয়েবলটিকে স্থির হিসাবে সংজ্ঞায়িত করা হয়েছে But তবে এটি কোনও সি লোকের দ্বারা উত্তমতর উত্তর হবে এবং আমার দ্বারা নয়। সি ++ সি এবং সি উভয়কে আপনার ভেরিয়েবলকে স্থির হিসাবে ঘোষণার উপায়গুলি অনুমতি দেয় কারণ এটি সম্পূর্ণরূপে সিটির সাথে সামঞ্জস্যপূর্ণ compatible


1

স্থানীয় পরিবর্তনশীল এর অর্থ কী? এটি কি একটি ফাংশন স্থানীয় পরিবর্তনশীল?

হ্যাঁ - অ-গ্লোবাল, যেমন কোনও ফাংশন স্থানীয় ভেরিয়েবল।

কারণ এমনও আছে যে আপনি যখন কোনও ফাংশন স্থির হিসাবে ঘোষণা করেন যে এটি কেবল একবার শুরু করা হয়েছিল, প্রথমবার এটি এই ফাংশনে প্রবেশ করে।

ঠিক।

এটি কেবল শ্রেণীর সদস্যদের সাথে স্টোরেজ সময়কাল সম্পর্কে আলোচনা করে, এটি অযৌক্তিক নির্দিষ্ট হওয়ার বিষয়ে কী, এটি স্ট্যাটিক নং এর সম্পত্তিও কি? নাকি সেই স্টোরেজ সময়কাল?

class R { static int a; }; // << static lives for the duration of the program

এর অর্থ, Rভাগের সমস্ত দৃষ্টান্ত int R::a- int R::aকখনও অনুলিপি করা হয় না।

এখন স্ট্যাটিক এবং ফাইল স্কোপ নিয়ে কেস কী হবে?

কার্যকরভাবে এমন একটি গ্লোবাল যেখানে কনস্ট্রাক্টর / ডেস্ট্রাক্টর রয়েছে যেখানে উপযুক্ত - সূচনা অ্যাক্সেস না হওয়া পর্যন্ত পিছিয়ে নেই।

স্থির একটি চলক সংযোগের সাথে কীভাবে সম্পর্কযুক্ত?

স্থানীয় একটি ফাংশন জন্য, এটি বাহ্যিক। অ্যাক্সেস: এটি ফাংশনে অ্যাক্সেসযোগ্য (অবশ্যই যদি না আপনি এটি ফিরিয়ে দেন)।

একটি শ্রেণীর জন্য, এটি বাহ্যিক। অ্যাক্সেস: স্ট্যান্ডার্ড অ্যাক্সেস স্পেসিফায়াররা প্রয়োগ করুন (সর্বজনীন, সুরক্ষিত, ব্যক্তিগত)।

static এটি কোথায় ঘোষিত হয়েছে তার উপর নির্ভর করে অভ্যন্তরীণ যোগসূত্র নির্দিষ্ট করতে পারে (ফাইল / নামস্থান)।

এই সম্পূর্ণ স্ট্যাটিক কীওয়ার্ডটি সরল বিভ্রান্তিকর

সি ++ তে এর অনেকগুলি উদ্দেশ্য রয়েছে।

কেউ কি ইংরেজির জন্য এর বিভিন্ন ব্যবহারগুলি স্পষ্ট করে বলতে পারেন এবং স্ট্যাটিক শ্রেণির সদস্যকে কখন আরম্ভ করতে হবে তাও আমাকে বলতে পারেন?

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


1

স্ট্যাটিক অবজেক্ট: স্ট্যাটিক কীওয়ার্ড ব্যবহার করে আমরা ক্লাসের সদস্যদের স্থির সংজ্ঞা দিতে পারি can আমরা যখন ক্লাসের কোনও সদস্যকে স্থিতিশীল হিসাবে ঘোষণা করি তখন এর অর্থ ক্লাসের কতগুলি বস্তু তৈরি করা হয় তা বিবেচনা না করে স্থির সদস্যের কেবল একটি অনুলিপি থাকে।

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

স্ট্যাটিক ডেটা সদস্যদের ধারণাটি বোঝার জন্য আসুন নীচের উদাহরণটি চেষ্টা করুন:

#include <iostream>

using namespace std;

class Box
{
   public:
      static int objectCount;
      // Constructor definition
      Box(double l=2.0, double b=2.0, double h=2.0)
      {
         cout <<"Constructor called." << endl;
         length = l;
         breadth = b;
         height = h;
         // Increase every time object is created
         objectCount++;
      }
      double Volume()
      {
         return length * breadth * height;
      }
   private:
      double length;     // Length of a box
      double breadth;    // Breadth of a box
      double height;     // Height of a box
};

// Initialize static member of class Box
int Box::objectCount = 0;

int main(void)
{
   Box Box1(3.3, 1.2, 1.5);    // Declare box1
   Box Box2(8.5, 6.0, 2.0);    // Declare box2

   // Print total number of objects.
   cout << "Total objects: " << Box::objectCount << endl;

   return 0;
}

যখন উপরের কোডটি সংকলিত এবং সম্পাদন করা হয়, তখন এটি নিম্নলিখিত ফলাফল উত্পন্ন করে:

Constructor called.
Constructor called.
Total objects: 2

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

স্ট্যাটিক সদস্য ফাংশনটি কেবল স্থিতিশীল ডেটা সদস্য, অন্যান্য স্থির সদস্য ফাংশন এবং শ্রেণীর বাইরে থেকে অন্য কোনও ফাংশন অ্যাক্সেস করতে পারে।

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

স্ট্যাটিক ফাংশন সদস্যদের ধারণাটি বুঝতে নীচের উদাহরণটি চেষ্টা করি:

#include <iostream>

using namespace std;

class Box
{
   public:
      static int objectCount;
      // Constructor definition
      Box(double l=2.0, double b=2.0, double h=2.0)
      {
         cout <<"Constructor called." << endl;
         length = l;
         breadth = b;
         height = h;
         // Increase every time object is created
         objectCount++;
      }
      double Volume()
      {
         return length * breadth * height;
      }
      static int getCount()
      {
         return objectCount;
      }
   private:
      double length;     // Length of a box
      double breadth;    // Breadth of a box
      double height;     // Height of a box
};

// Initialize static member of class Box
int Box::objectCount = 0;

int main(void)
{

   // Print total number of objects before creating object.
   cout << "Inital Stage Count: " << Box::getCount() << endl;

   Box Box1(3.3, 1.2, 1.5);    // Declare box1
   Box Box2(8.5, 6.0, 2.0);    // Declare box2

   // Print total number of objects after creating object.
   cout << "Final Stage Count: " << Box::getCount() << endl;

   return 0;
}

যখন উপরের কোডটি সংকলিত এবং সম্পাদন করা হয়, তখন এটি নিম্নলিখিত ফলাফল উত্পন্ন করে:

Inital Stage Count: 0
Constructor called.
Constructor called.
Final Stage Count: 2

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