আপনি সি ++ এ স্ট্যাটিক ক্লাসটি কীভাবে তৈরি করবেন? আমার মতো কিছু করতে সক্ষম হওয়া উচিত:
cout << "bit 5 is " << BitParser::getBitAt(buffer, 5) << endl;
ধরে নিচ্ছি আমি BitParserক্লাস তৈরি করেছি । BitParserক্লাস সংজ্ঞা কেমন হবে ?
আপনি সি ++ এ স্ট্যাটিক ক্লাসটি কীভাবে তৈরি করবেন? আমার মতো কিছু করতে সক্ষম হওয়া উচিত:
cout << "bit 5 is " << BitParser::getBitAt(buffer, 5) << endl;
ধরে নিচ্ছি আমি BitParserক্লাস তৈরি করেছি । BitParserক্লাস সংজ্ঞা কেমন হবে ?
উত্তর:
আপনি যদি উদাহরণস্বরূপ C # তে পারেন এমন কোনও ক্লাসে "স্ট্যাটিক" কীওয়ার্ড প্রয়োগ করার কোনও উপায় সন্ধান করছেন, তবে আপনি পরিচালিত সি ++ ব্যবহার না করে সক্ষম হবেন না।
তবে আপনার নমুনার চেহারা, আপনার বিট পার্সার অবজেক্টে আপনাকে একটি সর্বজনীন স্ট্যাটিক পদ্ধতি তৈরি করতে হবে। তাই ভালো:
BitParser.h
class BitParser
{
public:
static bool getBitAt(int buffer, int bitIndex);
// ...lots of great stuff
private:
// Disallow creating an instance of this object
BitParser() {}
};
BitParser.cpp
bool BitParser::getBitAt(int buffer, int bitIndex)
{
bool isBitSet = false;
// .. determine if bit is set
return isBitSet;
}
আপনি এই কোডটি আপনার উদাহরণ কোড হিসাবে একই পদ্ধতিতে কল করতে ব্যবহার করতে পারেন।
আশা করি এইটি কাজ করবে! চিয়ার্স।
private: BitParser() {}এটি যে কাউকে দৃষ্টান্ত তৈরি করতে বাধা দেবে।
BitParser() = delete;কন্সট্রাক্টর অপসারণের অভিপ্রায়টি সঠিকভাবে জানানো ভাল (কেবল এটি এটিকে আড়াল করা নয় private)।
ম্যাট প্রাইসের সমাধান বিবেচনা করুন ।
আপনি যা চান তা হ'ল সি ++ শব্দার্থবিজ্ঞানে প্রকাশিত, আপনার ফাংশনটি রাখার জন্য (এটি এটির জন্য একটি নামস্থান একটি ফাংশন)।
সি ++ তে কোনও "স্ট্যাটিক ক্লাস" নেই। নিকটতম ধারণাটি কেবল স্থির পদ্ধতি সহ একটি শ্রেণি হবে। উদাহরণ স্বরূপ:
// header
class MyClass
{
public :
static void myMethod() ;
} ;
// source
void MyClass::myMethod()
{
// etc.
}
তবে আপনাকে অবশ্যই মনে রাখতে হবে যে "স্ট্যাটিক ক্লাস" হ'ল জাভা জাতীয় ধরণের ভাষাগুলিতে হ্যাক (উদাহরণস্বরূপ সি #) যা সদস্যবিহীন কার্যাবলী রাখতে অক্ষম, সুতরাং তাদের পরিবর্তে স্থির পদ্ধতি হিসাবে শ্রেণীর ভিতরে স্থানান্তরিত করতে হবে।
সি ++ এ, আপনি যা চান তা হ'ল একটি অ-সদস্য ফাংশন যা আপনি একটি নেমস্পেসে ঘোষণা করবেন:
// header
namespace MyNamespace
{
void myMethod() ;
}
// source
namespace MyNamespace
{
void myMethod()
{
// etc.
}
}
সি ++ তে, "জাভা স্ট্যাটিক পদ্ধতি" প্যাটার্নের জন্য ক্লাসগুলির চেয়ে নেমস্পেস আরও শক্তিশালী, কারণ:
উপসংহার: জাভা / সি # এর প্যাটার্নটি সি ++ এ অনুলিপি / আটকান না। জাভা / সি # তে, প্যাটার্নটি বাধ্যতামূলক। তবে সি ++ এ এটি খারাপ স্টাইল।
স্থির পদ্ধতির পক্ষে একটি যুক্তি ছিল কারণ কখনও কখনও, একটি স্ট্যাটিক প্রাইভেট সদস্য ভেরিয়েবল ব্যবহার করা প্রয়োজন।
আমি কিছুটা দ্বিমত পোষণ করছি, যেমন নীচে দেখানো হয়েছে:
// HPP
class Foo
{
public :
void barA() ;
private :
void barB() ;
static std::string myGlobal ;
} ;
প্রথমত, মাইগ্লোবালকে মাইগ্লোবাল বলা হয় কারণ এটি এখনও বিশ্বব্যাপী ব্যক্তিগত পরিবর্তনশীল। সিপিপি উত্সটি একবারে স্পষ্ট করবে যে:
// CPP
std::string Foo::myGlobal ; // You MUST declare it in a CPP
void Foo::barA()
{
// I can access Foo::myGlobal
}
void Foo::barB()
{
// I can access Foo::myGlobal, too
}
void barC()
{
// I CAN'T access Foo::myGlobal !!!
}
প্রথম দর্শনে, ফ্রি ফাংশন বারক ফু অ্যাক্সেস করতে পারে না: মাইগ্লোবাল একটি এনক্যাপসুলেশন দৃষ্টিকোণ থেকে ভাল জিনিস বলে মনে হচ্ছে ... এটি দুর্দান্ত কারণ এইচপিপির দিকে নজর দেওয়া কোনও ব্যক্তি (নাশকতার অবলম্বন না করা) অ্যাক্সেস করতে পারবেন না foo বিন্যাস :: myGlobal।
তবে আপনি যদি এটি ঘনিষ্ঠভাবে দেখুন, আপনি দেখতে পাবেন যে এটি একটি বিশাল ভুল: কেবলমাত্র আপনার ব্যক্তিগত ভেরিয়েবলকে এইচপিপিতে এখনও ঘোষণা করা উচিত নয় (এবং তাই প্রাইভেট হয়েও সমস্ত বিশ্বের কাছে দৃশ্যমান), তবে আপনাকে অবশ্যই ঘোষণা করতে হবে একই এইচপিপিতে সমস্ত (সমস্ত হিসাবে) ফাংশন যা এটি অ্যাক্সেস করার জন্য অনুমোদিত হবে !!!
তাই কোনও প্রাইভেট স্ট্যাটিক সদস্য ব্যবহার করা আপনার ত্বকে উলকি আঁকা আপনার প্রেমীদের তালিকার সাথে ন্যুডে বাইরে হাঁটার মতো: কেউ স্পর্শ করার জন্য অনুমোদিত নয়, তবে সকলেই উঁকি দিতে সক্ষম। এবং বোনাস: আপনার গোপনীয়তা নিয়ে খেলতে অনুমোদিত প্রত্যেকের নাম থাকতে পারে।
private সত্যই ... :-D
বেনামে নামের জায়গাগুলিতে ব্যক্তিগত জিনিসগুলি ব্যক্তিগতভাবে ব্যক্তিগত করার সুবিধা থাকবে।
প্রথমত, এইচপিপি শিরোনাম
// HPP
namespace Foo
{
void barA() ;
}
আপনি যে মন্তব্য করেছেন তা নিশ্চিত হতে: বার্ব বা মাইগ্লোবালের কোনও অকেজো ঘোষণা নেই। যার অর্থ হ'ল হেডারটি পড়া কেউই জানে না বারের পিছনে কী লুকানো আছে।
তারপরে, সিপিপি:
// CPP
namespace Foo
{
namespace
{
std::string myGlobal ;
void Foo::barB()
{
// I can access Foo::myGlobal
}
}
void barA()
{
// I can access myGlobal, too
}
}
void barC()
{
// I STILL CAN'T access myGlobal !!!
}
আপনি দেখতে পাচ্ছেন, তথাকথিত "স্ট্যাটিক ক্লাস" ঘোষণার মতো, fooA এবং fooB এখনও মাইগ্লোবাল অ্যাক্সেস করতে সক্ষম। তবে আর কেউ পারে না। এবং এই সিপিপির বাইরে অন্য কেউ fooB এবং মাইগ্লোবাল এমনকি বিদ্যমান জানেন না!
"স্ট্যাটিক ক্লাস" তার ত্বকে উলকিযুক্ত তার ঠিকানা বইয়ের সাথে নগ্ন পায়ে হাঁটার মতো নয় "অনামী" নামের স্থানটি পুরোপুরি পরিহিত , এটি এএফএইকে বেশ উন্নত বলে মনে হয়।
যদি না আপনার কোড ব্যবহারকারীদের স্যাবোটাজ হয় (আমি তোমাকে জানাবো একটি ব্যায়াম হিসেবে এটি কিভাবে এক একটি মলিন আচরণ-অনির্ধারিত হ্যাক ব্যবহার ... একটি পাবলিক ক্লাস ব্যক্তিগত অংশ অ্যাক্সেস করতে পারেন,), কি privateহল private, যদিও তা privateশিরোনামে ঘোষিত শ্রেণীর বিভাগে দৃশ্যমান ।
তবুও, যদি আপনাকে ব্যক্তিগত সদস্যের অ্যাক্সেসের সাথে আরও একটি "ব্যক্তিগত ফাংশন" যুক্ত করতে হয়, তবে আপনাকে অবশ্যই শিরোনামটি সংশোধন করে সমস্ত বিশ্বের কাছে এটি ঘোষণা করতে হবে, যা আমি যতটা উদ্বিগ্ন, এটি একটি বিপরীত বিষয়: যদি আমি এর প্রয়োগ পরিবর্তন করি আমার কোড (সিপিপি অংশ), তারপরে ইন্টারফেসের (এইচপিপি অংশ) পরিবর্তন করা উচিত নয়। লিওনিদাসের উদ্ধৃতি দিয়ে: " এটি এনসিপিসুলেশন! "
ক্লাসের স্থির পদ্ধতিগুলি কখন সদস্যবিহীন ফাংশন সহ নেমস্পেসের চেয়ে ভাল হয়?
যখন আপনাকে একসাথে ফাংশনগুলি গোষ্ঠীভুক্ত করতে এবং সেই গোষ্ঠীটিকে কোনও টেমপ্লেটে ফিড করতে হবে:
namespace alpha
{
void foo() ;
void bar() ;
}
struct Beta
{
static void foo() ;
static void bar() ;
};
template <typename T>
struct Gamma
{
void foobar()
{
T::foo() ;
T::bar() ;
}
};
Gamma<alpha> ga ; // compilation error
Gamma<Beta> gb ; // ok
gb.foobar() ; // ok !!!
কারণ, কোনও শ্রেণি যদি একটি টেম্পলেট প্যারামিটার হতে পারে তবে একটি নেমস্পেস করতে পারে না।
#define private publicশিরোনামগুলিতে নিম্নলিখিত কোড যুক্ত করার জন্য একটি ক্রস-প্ল্যাটফর্ম সমাধান হ'ল ... ^ _ ^ ...
utilitiesহ'ল একটি নামস্থানে প্রয়োজনীয় প্যারামিটারগুলি (এবং আরও কিছু না) নিয়ে কোনও ফাংশনে পরীক্ষার জন্য কোডটি দেওয়া হবে । এইভাবে, এই ফাংশনটি ইউনিট-টেস্ট করা যেতে পারে, এবং এখনও ব্যক্তিগত সদস্যদের কোনও বিশেষ অ্যাক্সেস নেই (যেমন ফাংশন কলটিতে তারা প্যারামিটার হিসাবে দেওয়া হয়) ...
namespaceআপনার global, অ্যাক্সেস পাবে না ? অবশ্যই তাদের অনুমান করতে হবে, তবে আপনি যদি নিজের ইচ্ছাকৃতভাবে আপনার কোডটি অবলম্বন না করেন তবে পরিবর্তনশীল নামগুলি অনুমান করা খুব সহজ।
আপনি একটি নেমস্পেসে একটি ফ্রি ফাংশন তৈরি করতে পারেন:
বিট পার্সার। এ
namespace BitParser
{
bool getBitAt(int buffer, int bitIndex);
}
বিটপার্সার.সি.পি. তে
namespace BitParser
{
bool getBitAt(int buffer, int bitIndex)
{
//get the bit :)
}
}
সাধারণভাবে কোডটি লেখার পক্ষে এটি পছন্দনীয় উপায়। যখন কোনও জিনিসের প্রয়োজন নেই তখন ক্লাস ব্যবহার করবেন না।
আপনি যদি কোনও ক্লাসে "স্ট্যাটিক" কীওয়ার্ড প্রয়োগ করার কোনও উপায় সন্ধান করছেন, যেমন আপনি সি # তে পারেন
স্ট্যাটিক ক্লাসগুলি হ'ল সংকলক আপনাকে হ্যান্ড হোল্ড করে এবং আপনাকে কোনও উদাহরণ পদ্ধতি / ভেরিয়েবল লিখতে বাধা দেয়।
যদি আপনি কেবল কোনও উদাহরণের পদ্ধতি / ভেরিয়েবলগুলি ছাড়াই একটি সাধারণ ক্লাস লিখেন তবে এটি একই জিনিস এবং আপনি সি ++ এ যা করতে চান
static200 বার শব্দটি আমার লেখা বা কাটা / আটকাতে বাধা দেওয়ার জন্য কয়েকটি সংকলক হ্যান্ড হোল্ড করা ভাল জিনিস হবে।
সি ++ এ আপনি কোনও শ্রেণির একটি স্ট্যাটিক ফাংশন তৈরি করতে চান (কোনও স্ট্যাটিক শ্রেণি নয়)।
class BitParser {
public:
...
static ... getBitAt(...) {
}
};
তারপরে আপনি বিট পার্সার ব্যবহার করে ফাংশনটি কল করতে সক্ষম হবেন: getBitAt () কোনও বস্তুর তাত্ক্ষণিক না করে যা আমি মনে করি এটি পছন্দসই ফলাফল।
আমি কি কিছু লিখতে পারি static class?
না , সি ++ 11 এন 3337 স্ট্যান্ডার্ড খসড়া অনুসারে এন সি সি 7.1.1:
পরিবর্তন: সি ++ এ স্থিতিশীল বা বহিরাগত স্পেসিফায়ার কেবলমাত্র বস্তুর বা ফাংশনের নামে প্রয়োগ করা যেতে পারে। প্রকারের ঘোষণার সাথে এই স্পেসিফায়ার ব্যবহার করা সি ++ এ অবৈধ। সি-তে, প্রকারের ঘোষণার সময় এই নির্দিষ্টকরণকারীগুলিকে উপেক্ষা করা হয়। উদাহরণ:
static struct S { // valid C, invalid in C++ int i; };যুক্তি: স্টোরের ক্লাস স্পেসিফায়ারদের কোনও প্রকারের সাথে সম্পর্কিত হওয়ার কোনও অর্থ হয় না। সি ++ এ, শ্রেণীর সদস্যদের স্থিতিশীল স্টোরেজ শ্রেণীর নির্দিষ্টকরণকারক সহ ঘোষণা করা যেতে পারে। প্রকারের ঘোষণায় স্টোরেজ শ্রেণীর নির্দিষ্টকরণের অনুমতি দেওয়া ব্যবহারকারীদের জন্য বিভ্রান্তিকর কোডটি রেন্ডার করতে পারে।
এবং মত struct, classএটিও একটি প্রকারের ঘোষণা।
আনেকেক্স এ সিনট্যাক্স ট্রি হাঁটার মাধ্যমে একই অনুমান করা যায়
এটি লক্ষণীয় আকর্ষণীয় যে static structসি তে আইনী ছিল, তবে তার কোনও প্রভাব ছিল না: সি প্রোগ্রামিংয়ে স্থির কাঠামো কেন এবং কখন ব্যবহার করবেন?
যেমনটি এখানে উল্লেখ করা হয়েছে, সি ++ এ অর্জনের একটি আরও ভাল উপায় নেমস্পেস ব্যবহার করতে পারে। তবে যেহেতু finalএখানে কীওয়ার্ডটি কেউ উল্লেখ করেনি , তাই আমি পোস্ট করছি যে static classসি # থেকে সরাসরি সমতুল্য C ++ 11 বা তার পরে কি দেখাবে:
class BitParser final
{
public:
BitParser() = delete;
static bool GetBitAt(int buffer, int pos);
};
bool BitParser::GetBitAt(int buffer, int pos)
{
// your code
}
আপনার সি ++ তে একটি স্ট্যাটিক ক্লাস থাকতে পারে, যেমনটি আগেই উল্লেখ করা হয়েছে, একটি স্ট্যাটিক ক্লাস এমন একটি যাতে এর কোনও অবজেক্ট থাকে না এটি ইনস্ট্যান্ট করে দেয়। সি ++ এ, নির্মাণকারী / ডেস্ট্রাক্টরকে ব্যক্তিগত হিসাবে ঘোষণা করে এটি প্রাপ্ত করা যায়। শেষ ফলাফল একই।
এটি সি ++-তে এটি করার জন্য সি # এর মতো
সি # file.cs এ আপনি কোনও পাবলিক ফাংশনের অভ্যন্তরে ব্যক্তিগত ভেরি রাখতে পারেন। অন্য কোনও ফাইলে থাকাকালীন ফাংশনটির সাথে নামস্থানে কল করে আপনি এটি ব্যবহার করতে পারেন:
MyNamespace.Function(blah);
সি ++ তে কীভাবে এটি চাপিয়ে দেওয়া যায় তা এখানে:
SharedModule.h
class TheDataToBeHidden
{
public:
static int _var1;
static int _var2;
};
namespace SharedData
{
void SetError(const char *Message, const char *Title);
void DisplayError(void);
}
SharedModule.cpp
//Init the data (Link error if not done)
int TheDataToBeHidden::_var1 = 0;
int TheDataToBeHidden::_var2 = 0;
//Implement the namespace
namespace SharedData
{
void SetError(const char *Message, const char *Title)
{
//blah using TheDataToBeHidden::_var1, etc
}
void DisplayError(void)
{
//blah
}
}
OtherFile.h
#include "SharedModule.h"
OtherFile.cpp
//Call the functions using the hidden variables
SharedData::SetError("Hello", "World");
SharedData::DisplayError();
অন্যান্য পরিচালিত প্রোগ্রামিং ভাষার মতো নয়, "স্ট্যাটিক ক্লাস" এর সি ++ এর কোনও অর্থ নেই। আপনি স্থিতিশীল সদস্য ফাংশন ব্যবহার করতে পারেন।
উত্তরাধিকারের উপরের রচনা অর্জনের জন্য এই ক্লাসগুলি ব্যবহার করার সময় নেমস্পেসগুলি "স্ট্যাটিক ক্লাস" অর্জনের জন্য এত কার্যকর নাও হতে পারে One নেমস্পেসগুলি ক্লাসের বন্ধু হতে পারে না এবং তাই কোনও শ্রেণীর ব্যক্তিগত সদস্যদের অ্যাক্সেস করতে পারে না।
class Class {
public:
void foo() { Static::bar(*this); }
private:
int member{0};
friend class Static;
};
class Static {
public:
template <typename T>
static void bar(T& t) {
t.member = 1;
}
};
একটি (অনেকের মধ্যে) বিকল্প, তবে সর্বাধিক (আমার মতে) মার্জিত (স্থির আচরণের অনুকরণের জন্য নেমস্পেস এবং ব্যক্তিগত নির্মাণকারীদের তুলনায়), সি ++ তে "শ্রেণি যা ইনস্ট্যান্ট করা যায় না" অর্জনের উপায় হ'ল privateঅ্যাক্সেস মডিফায়ার সহ একটি ডামি বিশুদ্ধ ভার্চুয়াল ফাংশন ঘোষণা করুন ।
class Foo {
public:
static int someMethod(int someArg);
private:
virtual void __dummy() = 0;
};
আপনি যদি C ++ 11 ব্যবহার করেন তবে ক্লাসের উত্তরাধিকার সূত্রে প্রাপ্ত নয় তা নিশ্চিত করার জন্য আপনি আরও মাইল যেতে পারতেন ( finalক্লাসের ঘোষণাপত্রের স্পেসিফায়ার ব্যবহার করে অন্যান্য ক্লাসকে উত্তরাধিকার সূত্রে সীমাবদ্ধ রাখার জন্য ।
// C++11 ONLY
class Foo final {
public:
static int someMethod(int someArg);
private:
virtual void __dummy() = 0;
};
নির্বোধ এবং অযৌক্তিক যেমনটি শোনা যায় তত, সি ++ 11 একটি "খাঁটি ভার্চুয়াল ফাংশন যা ওভাররাইড করা যায় না" ঘোষণার অনুমতি দেয়, যা আপনি ক্লাসে ঘোষণার পাশাপাশি ব্যবহার করতে পারেন finalবিশুদ্ধভাবে এবং সম্পূর্ণরূপে স্থির আচরণকে বাস্তবায়িত করার ফলে ফলাফল হিসাবে বর্গ উত্তরাধিকারসূত্রে না হবে এবং ডামি ফাংশন কোনওভাবেই ওভাররাইড করা হবে না।
// C++11 ONLY
class Foo final {
public:
static int someMethod(int someArg);
private:
// Other private declarations
virtual void __dummy() = 0 final;
}; // Foo now exhibits all the properties of a static class