সি ++ এ স্ট্যাটিক কনস্ট্রাক্টর? আমার ব্যক্তিগত স্ট্যাটিক অবজেক্টগুলি শুরু করতে হবে initial


176

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

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

যদি আমি উদাহরণস্বরূপ কনস্ট্রাক্টরে তাদের আরম্ভ করতে না চাই তবে কি ক্লাসে প্রাইভেট স্ট্যাটিক ডেটা সদস্য থাকা সম্ভব?



1
@ সিরোস্যান্টিলি 新疆 改造 中心 六四 事件 法轮功 এই প্রশ্নটি প্রাইভেট স্থিতিশীল আদিম ধরণের ধ্রুবক মান নির্ধারণ না করে প্রাইভেট স্ট্যাটিক অবজেক্টগুলিকে সূচনা করার জন্য চলমান কোডের দিকে দৃষ্টি নিবদ্ধ করছে । সমাধানগুলি আলাদা।
গর্ডন গুস্তাফসন

আহ, আমি মনে করি আপনি ঠিক আছেন, প্রত্যাহার করছেন।
সিরো সান্তিলি 郝海东 冠状 病 六四 事件 法轮功

উত্তর:


180

স্ট্যাটিক কনস্ট্রাক্টরের সমতুল্য পেতে, আপনার স্ট্যাটিক ডেটা ধরে রাখতে একটি পৃথক সাধারণ বর্গ লিখতে হবে এবং তারপরে সেই সাধারণ শ্রেণির একটি স্ট্যাটিক উদাহরণ তৈরি করতে হবে।

class StaticStuff
{
     std::vector<char> letters_;

public:
     StaticStuff()
     {
         for (char c = 'a'; c <= 'z'; c++)
             letters_.push_back(c);
     }

     // provide some way to get at letters_
};

class Elsewhere
{
    static StaticStuff staticStuff; // constructor runs once, single instance

};

12
ধন্যবাদ! যদিও এটি করতে খুব বিরক্তিকর। সি # এবং জাভা অনেকগুলি "ভুল" এর মধ্যে একটি শিখেছে।
গর্ডন গুস্তাফসন

109
হ্যাঁ. আমি সবসময় লোকদের দিকে ইঙ্গিত করি যে সি ++ যদি এই সমস্ত "ভুল" না করে থাকে তবে অন্যান্য ভাষাগুলি এগুলি করতে হবে। সি ++ এত বেশি ভিত্তি coveringেকে রাখা, এমনকি ভুল করাও, এটি অনুসরণকারী ভাষাগুলির জন্য দুর্দান্ত হয়েছে।
কোয়ার্ক

11
স্ট্র্যাটিক অবজেক্টের কনস্ট্রাক্টর এক্সিকিউট করলে কনস্ট্রাক্টররা গ্যারান্টি দেয় না কেন কেবল একটি সামান্য অবহেলা। একটি সুপরিচিত অনেক নিরাপদ পদ্ধতির ক্লাস অন্যত্র where স্ট্যাটিকস্টাফ এবং get_staticStuff () {স্ট্যাটিক স্ট্যাটিকস্টাফ স্ট্যাটিক স্টাফ; // কনস্ট্রাক্টর একবার চালায়, যখন কারও প্রথমে প্রয়োজন হয় এটি স্ট্যাটিক স্টাফ ফেরত দেয়; }}; আমি ভাবছি যদি সি # এবং জাভাতে স্থির
নির্মাতারা

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

13
এটি প্রকৃতপক্ষে এমন একটি ক্ষেত্রে যেখানে friendবোধগম্যতা তৈরি করে যাতে শ্রেণি Elsewhereসহজেই StaticStuffঅভ্যন্তরীণ প্রবেশ করতে পারে (কোনও বিপজ্জনক উপায়ে এনক্যাপসুলেশন না ভেঙে আমি যুক্ত করতে পারি)।
কনরাড রুডলফ

81

ভাল আপনি করতে পারেন

class MyClass
{
    public:
        static vector<char> a;

        static class _init
        {
          public:
            _init() { for(char i='a'; i<='z'; i++) a.push_back(i); }
        } _initializer;
};

এটিকে (.cpp এ) ভুলে যাবেন না:

vector<char> MyClass::a;
MyClass::_init MyClass::_initializer;

প্রোগ্রামটি এখনও দ্বিতীয় লাইন ছাড়াই লিঙ্ক করবে, তবে প্রারম্ভিকটি কার্যকর করা হবে না।


+1 (এটি চেষ্টা করে দেখেনি) তবে: কবে _র_ইনিট ?_আইনাইট () বলা হয়? আমার যখন স্ট্যাটিক মাই ক্লাস অবজেক্ট থাকে তখন মাইক্লাসের কর্টরের আগে বা পরে? আমার ধারণা আপনি বলতে পারবেন না ...

2
হ্যালো, আমি এই "আরম্ভকারী" যাদু সম্পর্কে আরও কোথায় জানতে পারি?
কারেল বালেক

এর MyClass::a.push_back(i)পরিবর্তে হওয়া উচিত নয় a.push_back(i)?
নীল বসু

4
@ আমাদের .: _initializerএকটি সাবজেক্ট MyClass। সাবওজেক্টসটি এই ক্রমে সূচনা করা হয়েছে: ভার্চুয়াল বেস শ্রেণীর সাবোবজেক্টগুলি, গভীরতা-প্রথম, বাম-থেকে-ডান ক্রমে (তবে কেবলমাত্র প্রতিটি স্বতন্ত্র সাব-সাবজেক্ট একবার একবার শুরু করা); তারপরে প্লেইন বেস ক্লাস সাবোবজেক্টস, গভীরতা-প্রথম, বাম থেকে ডান ক্রমে; তারপরে ঘোষণার ক্রমে সদস্য সাবওবজেক্টস। সুতরাং ইফ্রাইমের কৌশলটি ব্যবহার করা নিরাপদ, শর্ত রয়েছে যে কোডটি _initialiserকেবল এর আগে ঘোষিত সদস্যদের বোঝায়।
j_random_hacker

2
এই উত্তর গৃহীত উত্তরগুলির চেয়ে ভাল কারণ লেখক দ্বিতীয় কোড ক্লিপটিতে অনিবার্য প্রারম্ভিক উল্লেখ করেছিলেন।
জেফ টি।

33

সি ++ 11 সমাধান

যেহেতু সি ++ 11, আপনি স্থির শ্রেণির সদস্যদের সূচনা করার জন্য ল্যাম্বডা এক্সপ্রেশনটি কেবল ব্যবহার করতে পারেন । এটি এমনকি যদি আপনার বিভিন্ন স্থিতিশীল সদস্যদের মধ্যে নির্মাণের অর্ডার চাপানোর প্রয়োজন হয় বা আপনার যদি স্থির সদস্য থাকে তবে এটি কাজ করে const

শিরোনাম ফাইল:

class MyClass {
    static const vector<char> letters;
    static const size_t letterCount;
};

উত্স ফাইল:

// Initialize MyClass::letters by using a lambda expression.
const vector<char> MyClass::letters = [] {
    vector<char> letters;
    for (char c = 'a'; c <= 'z'; c++)
        letters.push_back(c);
    return letters;
}();

// The initialization order of static members is defined by the order of
// definition within the source file, so we can access MyClass::letters here.
const size_t MyClass::letterCount = letters.size();

আকর্ষণীয় সমাধান। এই ক্ষেত্রে আমি যদি একটি ব্যতিক্রম ছুঁড়ে ফেলি তবে কে এটি ধরতে পারে?
রাফি উইনার

5
স্ট্যাটিক প্রোগ্রামের সূচনা কোডটি অবশ্যই কোনও ব্যতিক্রম ছুঁড়ে ফেলবে না , বা প্রোগ্রামটি ক্রাশ হবে। try catchব্যতিক্রমগুলি ছুঁড়ে ফেলা হতে পারে আপনাকে অবশ্যই একটি প্রাথমিক ব্লক মধ্যে প্রারম্ভক যুক্তি যুক্ত করতে হবে।
emkey08

19

.H ফাইলটিতে:

class MyClass {
private:
    static int myValue;
};

.Cpp ফাইলে:

#include "myclass.h"

int MyClass::myValue = 0;

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

আমি ঠিক এটি করছি, তবে এটি এখনও সংকলন করে না। এবং এটি বলেছে এটি সমস্যা ক্ষেত্র (কনস্ট্রাক্টারে, শিরক নয়)
ফ্লোটক

14

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

শিরোনাম ফাইল:

class ToBeInitialized
{
    // Inner friend utility class to initialize whatever you need

    class Initializer
    {
    public:
        Initializer();
    };

    friend class Initializer;

    // Static member variables of ToBeInitialized class

    static const int numberOfFloats;
    static float *theFloats;

    // Static instance of Initializer
    //   When this is created, its constructor initializes
    //   the ToBeInitialized class' static variables

    static Initializer initializer;
};

বাস্তবায়ন ফাইল:

// Normal static scalar initializer
const int ToBeInitialized::numberOfFloats = 17;

// Constructor of Initializer class.
//    Here is where you can initialize any static members
//    of the enclosing ToBeInitialized class since this inner
//    class is a friend of it.

ToBeInitialized::Initializer::Initializer()
{
    ToBeInitialized::theFloats =
        (float *)malloc(ToBeInitialized::numberOfFloats * sizeof(float));

    for (int i = 0; i < ToBeInitialized::numberOfFloats; ++i)
        ToBeInitialized::theFloats[i] = calculateSomeFancyValue(i);
}

এই পদ্ধতির বাইরের বিশ্ব থেকে প্রাথমিকভাবে ক্লাসটি গোপন করার সুবিধা রয়েছে, ক্লাসের মধ্যে থাকা সমস্ত কিছুকে আরম্ভ করার জন্য রেখে দেওয়া।


+1 একটি উদাহরণ দেওয়ার জন্য যা প্রয়োগকে নিজের ফাইলটিতে রাখে keeps
অ্যান্ড্রু লারসন

1
এছাড়াও, আপনাকে অবশ্যই তা কল হয়ে গেছে তা নিশ্চিত করতে হবে ToBeInitialized::Initializer::Initializer(), তাই আপনাকে ToBeInitialized::Initializer ToBeInitialized::initializer;বাস্তবায়ন ফাইলে যুক্ত করতে হবে। আমি আপনার ধারণা এবং ইফ্রাইমের ধারণা থেকে কিছু জিনিস নিয়েছি এবং এটি আমার যেমন প্রয়োজন ঠিক তেমন কাজ করে এবং পরিষ্কার দেখায়। ধন্যবাদ মানুষ.
অ্যান্ড্রু লারসন

11

Test::StaticTest() বৈশ্বিক স্ট্যাটিক ইনিশিয়েশনের সময় ঠিক একবার বলা হয়।

কলারকে কেবল ফাংশনে একটি লাইন যুক্ত করতে হবে যা তাদের স্থির নির্মাতা হবে।

static_constructor<&Test::StaticTest>::c;cগ্লোবাল স্ট্যাটিক ইনিশিয়ালেশন চলাকালীন সময়ে সূচনা জোর করে ।

template<void(*ctor)()>
struct static_constructor
{
    struct constructor { constructor() { ctor(); } };
    static constructor c;
};

template<void(*ctor)()>
typename static_constructor<ctor>::constructor static_constructor<ctor>::c;

/////////////////////////////

struct Test
{
    static int number;

    static void StaticTest()
    {
        static_constructor<&Test::StaticTest>::c;

        number = 123;
        cout << "static ctor" << endl;
    }
};

int Test::number;

int main(int argc, char *argv[])
{
    cout << Test::number << endl;
    return 0;
}

এটি একটি চমত্কার সমাধান। আমি ডগলাস ম্যান্ডেলের উত্তরটিও সত্যিই পছন্দ করি তবে এটি আরও সংক্ষিপ্ত।
ফ্লিন্টজেডা

এটি সত্যিই আশ্চর্যজনক!
nh_

9

কোনও init()ক্রিয়াকলাপের প্রয়োজন নেই , std::vectorএকটি ব্যাপ্তি থেকে তৈরি করা যেতে পারে:

// h file:
class MyClass {
    static std::vector<char> alphabet;
// ...
};

// cpp file:
#include <boost/range.hpp>
static const char alphabet[] = "abcdefghijklmnopqrstuvwxyz";
std::vector<char> MyClass::alphabet( boost::begin( ::alphabet ), boost::end( ::alphabet ) );

নোট করুন, তবে, শ্রেণির ধরণের স্ট্যাটিকগুলি লাইব্রেরিতে সমস্যা সৃষ্টি করে, সুতরাং সেগুলি এড়ানো উচিত।

সি ++ 11 আপডেট

সি ++ 11 হিসাবে, আপনি পরিবর্তে এটি করতে পারেন:

// cpp file:
std::vector<char> MyClass::alphabet = { 'a', 'b', 'c', ..., 'z' };

এটি মূল উত্তরে সি ++ 98 সমাধানের মতো শব্দার্থগত সমতুল্য, তবে আপনি ডান হাতের স্ট্রিংটি আক্ষরিক ব্যবহার করতে পারবেন না, সুতরাং এটি সম্পূর্ণ উচ্চতর নয়। যাইহোক, যদি আপনি অন্য কোন ধরনের একটি ভেক্টর আছে চেয়ে char, wchar_t, char16_tবা char32_t(অ্যারে যার স্ট্রিং লিটারেল হিসেবে লেখা যেতে পারে), সি ++ 11 সংস্করণ কঠোরভাবে অন্যান্য সিনট্যাক্স উপস্থাপক ছাড়া boilerplate কোড সরাবে সি ++ 98 তুলনায় সংস্করণ।


আমি এটা পছন্দ করি. যদিও কেবল যদি আমরা এটি এখন ব্যবহারযোগ্য বর্ণমালা ছাড়াই এক লাইনে করতে পারতাম।
মার্টিন ইয়র্ক

লাইব্রেরিগুলিতে সমস্যা সৃষ্টির জন্য, স্থির শ্রেণিটি ব্যক্তিগত বা জনসাধারণের ক্ষেত্রে কী আসে যায়? অধিকন্তু, লাইব্রেরিটি স্থির (.a) বা গতিশীল (.so) কিনা তা বিবেচনা করে?
জাকারি ক্রাউস

@ জাচারি ক্রাউস: পাবলিক / প্রাইভেট ক্লাস কী? এবং না, সমস্যাগুলি পৃথক হয়ে গেলেও ওভারল্যাপিংয়ের পরে, লাইব্রেরিটি স্থিতিশীলভাবে বা গতিশীলভাবে লিঙ্কযুক্ত কিনা তা বিবেচ্য নয়।
মার্ক মুটজ - মিমুতজ

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

@ জাচারি ক্রাউস: স্ট্যাটিক্সের প্রধান সমস্যা হ'ল ডায়নামিক ইনিশিয়েশন ([বেসিক.স্টার্ট.ইনাইটে / 2) প্রয়োজন যা তারা কোড চালায়। লাইব্রেরিগুলিতে, এটি হতে পারে যে ডেস্ট্রাক্টরগুলি চালিত হলে লাইব্রেরি কোডটি ইতিমধ্যে আনলোড করা হয়েছে। আপনি যদি আরও শুনতে চান তবে আমি এটি সম্পর্কে একটি প্রশ্ন পোস্ট করার পরামর্শ দিই।
মার্ক মুটজ - মিমুটিজ

6

সি ++ এর সমস্যাগুলি জানার পরে জাভাতে স্থির নির্মাতাদের ধারণাটি চালু হয়েছিল was সুতরাং আমাদের কোন সরাসরি সমতুল্য নেই।

সর্বোত্তম সমাধান হ'ল পিওডি প্রকারগুলি ব্যবহার করা যা স্পষ্টভাবে সূচনা করা যেতে পারে।
বা আপনার স্থির সদস্যদের একটি নির্দিষ্ট ধরণের তৈরি করুন যার নিজস্ব নির্মাতা রয়েছে যা এটি সঠিকভাবে আরম্ভ করবে।

//header

class A
{
    // Make sure this is private so that nobody can missues the fact that
    // you are overriding std::vector. Just doing it here as a quicky example
    // don't take it as a recomendation for deriving from vector.
    class MyInitedVar: public std::vector<char>
    {
        public:
        MyInitedVar()
        {
           // Pre-Initialize the vector.
           for(char c = 'a';c <= 'z';++c)
           {
               push_back(c);
           }
        }
    };
    static int          count;
    static MyInitedVar  var1;

};


//source
int            A::count = 0;
A::MyInitedVar A::var1;

4

ক্লাসটি সংকলন এবং ব্যবহার করার চেষ্টা করার সময় Elsewhere( আর্উইকারের উত্তর থেকে ) আমি পাই:

error LNK2001: unresolved external symbol "private: static class StaticStuff Elsewhere::staticStuff" (?staticStuff@Elsewhere@@0VStaticStuff@@A)

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

এই সংকলনটি তৈরি করতে আপনি তার পরিবর্তে " ভিতরে একটি স্থির স্থানীয় ভেরিয়েবল সহ একটি স্ট্যাটিক পদ্ধতি " ব্যবহার করতে পারেন । এটার মতো কিছু:

class Elsewhere
{
public:
    static StaticStuff& GetStaticStuff()
    {
        static StaticStuff staticStuff; // constructor runs once, single instance
        return staticStuff;
    }
};

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

হুগো গঞ্জালেজ কাস্ত্রো।


যদিও থ্রেড ব্যবহার করে সতর্ক হন। আমি জিসিসিতে বিশ্বাস করি যে স্থির স্থানীয়দের নির্মাণ সমবর্তী সম্পাদনের বিরুদ্ধে সুরক্ষিত আছে, তবে ভিজ্যুয়াল সি ++ তে এটি হয় না।
ড্যানিয়েল আরউইকার

1
C ++ থেকে 11 অগ্রে এবং POSIX, এটা হয়েছে থ্রেড-নিরাপদ যাবে।
মার্ক মুটজ - মিমুতজ

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

অসাধারণ! এটি এটি সম্পূর্ণ করে।
গ্যাবে হালসমার

4

আমি অনুমান করি এর সহজ সমাধানটি হ'ল:

    //X.h
    #pragma once
    class X
    {
    public:
            X(void);
            ~X(void);
    private:
            static bool IsInit;
            static bool Init();
    };

    //X.cpp
    #include "X.h"
    #include <iostream>

    X::X(void)
    {
    }


    X::~X(void)
    {
    }

    bool X::IsInit(Init());
    bool X::Init()
    {
            std::cout<< "ddddd";
            return true;
    }

    // main.cpp
    #include "X.h"
    int main ()
    {
            return 0;
    }

আমিও এটি করি।
ইথেরিয়লোনে

1

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

এখানে চূড়ান্ত কোড:

আমি কোডটি সহজীকরণ করেছি এবং র্যান্ড () ফাংশন এবং এর একক বীজ প্রারম্ভিক শ্রাদ () ব্যবহার করি

interface IRandClass
{
 public:
    virtual int GetRandom() = 0;
};

class RandClassSingleton
{
private:
  class RandClass : public IRandClass
  {
    public:
      RandClass()
      {
        srand(GetTickCount());
      };

     virtual int GetRandom(){return rand();};
  };

  RandClassSingleton(){};
  RandClassSingleton(const RandClassSingleton&);

  // static RandClass m_Instance;

  // If you declare m_Instance here you need to place
  // definition for this static object somewhere in your cpp code as
  // RandClassSingleton::RandClass RandClassSingleton::m_Instance;

  public:

  static RandClass& GetInstance()
  {
      // Much better to instantiate m_Instance here (inside of static function).
      // Instantiated only if this function is called.

      static RandClass m_Instance;
      return m_Instance;
  };
};

main()
{
    // Late binding. Calling RandClass ctor only now
    IRandClass *p = &RandClassSingleton::GetInstance();
    int randValue = p->GetRandom();
}
abc()
{
    IRandClass *same_p = &RandClassSingleton::GetInstance();
}

1

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

ইন .hফাইল, আপনি আছে:

template <typename Aux> class _MyClass
{
    public:
        static vector<char> a;
        _MyClass() {
            (void) _initializer; //Reference the static member to ensure that it is instantiated and its initializer is called.
        }
    private:
        static struct _init
        {
            _init() { for(char i='a'; i<='z'; i++) a.push_back(i); }
        } _initializer;

};
typedef _MyClass<void> MyClass;

template <typename Aux> vector<char> _MyClass<Aux>::a;
template <typename Aux> typename _MyClass<Aux>::_init _MyClass<Aux>::_initializer;

ইন .cppফাইল, আপনি পারেন:

void foobar() {
    MyClass foo; // [1]

    for (vector<char>::iterator it = MyClass::a.begin(); it < MyClass::a.end(); ++it) {
        cout << *it;
    }
    cout << endl;
}

নোটটি MyClass::aকেবল তখনই শুরু করা হয় যদি লাইন [1] সেখানে থাকে, কারণ যে কনস্ট্রাক্টরকে কল করে (এবং তার ইনস্ট্যান্টেশন প্রয়োজন), যার পরে তড়িঘড়ি প্রয়োজন _initializer


1

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

#include <iostream>
#include <vector>
using namespace std;

namespace {
  vector<int> vec;

  struct I { I() {
    vec.push_back(1);
    vec.push_back(3);
    vec.push_back(5);
  }} i;
}

int main() {

  vector<int>::const_iterator end = vec.end();
  for (vector<int>::const_iterator i = vec.begin();
       i != end; ++i) {
    cout << *i << endl;
  }

  return 0;
}

যদিও আপনি নাম Iএবং iকিছুটা আরও অস্পষ্ট করতে চাইতে পারেন তাই আপনি দুর্ঘটনাক্রমে ফাইলের নিচে কোথাও এটিকে ব্যবহার করবেন না।
জিম হুনজিকার

1
সত্যি বলতে কী, কেউ কেন বাস্তবায়নের ফাইলগুলিতে অনিয়ম নামকরণের চেয়ে ব্যক্তিগত স্থিতিশীল সদস্যদের ব্যবহার করতে চান তা দেখা মুশকিল।
জিম হুনজিকার

1

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

.hpp ফাইল:

vector<char> const & letters();

.cpp ফাইল:

vector<char> const & letters()
{
  static vector<char> v = {'a', 'b', 'c', ...};
  return v;
}


0

স্থায়ী সদস্য ভেরিয়েবলগুলি আপনি जसভাবে সদস্য পদ্ধতিগুলি সংজ্ঞায়িত করেন ঠিক তেমন সংজ্ঞা দেন।

foo.h

class Foo
{
public:
    void bar();
private:
    static int count;
};

foo.cpp

#include "foo.h"

void Foo::bar()
{
    // method definition
}

int Foo::count = 0;

2
CrazyJugglerDrummer প্রশ্নটি কোনও স্থির প্লেইন পুরাতন ডেটা টাইপ সম্পর্কে নয় :)
jww

0

একটি স্ট্যাটিক ভেরিয়েবল শুরু করতে, আপনি কেবল উত্স ফাইলের ভিতরে এটি করেন। উদাহরণ স্বরূপ:

//Foo.h
class Foo
{
 private:
  static int hello;
};


//Foo.cpp
int Foo::hello = 1;

CrazyJugglerDrummer প্রশ্নটি কোনও স্থির প্লেইন পুরাতন ডেটা টাইপ সম্পর্কে নয় :)
jww

0

সি # এর আচরণ নকল করতে একটি টেমপ্লেট তৈরি করার পদ্ধতি সম্পর্কে কীভাবে।

template<class T> class StaticConstructor
{
    bool m_StaticsInitialised = false;

public:
    typedef void (*StaticCallback)(void);

    StaticConstructor(StaticCallback callback)
    {
        if (m_StaticsInitialised)
            return;

        callback();

        m_StaticsInitialised = true;
    }
}

template<class T> bool StaticConstructor<T>::m_StaticsInitialised;

class Test : public StaticConstructor<Test>
{
    static std::vector<char> letters_;

    static void _Test()
    {
        for (char c = 'a'; c <= 'z'; c++)
            letters_.push_back(c);
    }

public:
    Test() : StaticConstructor<Test>(&_Test)
    {
        // non static stuff
    };
};

0

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

#include <iostream>

class MyClass 
{

    static const char * const letters(void){
        static const char * const var = "abcdefghijklmnopqrstuvwxyz";
        return var;
    }

    public:
        void show(){
            std::cout << letters() << "\n";
        }
};


int main(){
    MyClass c;
    c.show();
}

0

এটি কি সমাধান?

class Foo
{
public:
    size_t count;
    Foo()
    {
        static size_t count = 0;
        this->count = count += 1;
    }
};

0

একটি স্ট্যাটিক কনস্ট্রাক্টর নীচের মত একটি বন্ধু শ্রেণি বা নেস্টেড বর্গ ব্যবহার করে অনুকরণ করা যেতে পারে।

class ClassStatic{
private:
    static char *str;
public:
    char* get_str() { return str; }
    void set_str(char *s) { str = s; }
    // A nested class, which used as static constructor
    static class ClassInit{
    public:
        ClassInit(int size){ 
            // Static constructor definition
            str = new char[size];
            str = "How are you?";
        }
    } initializer;
};

// Static variable creation
char* ClassStatic::str; 
// Static constructor call
ClassStatic::ClassInit ClassStatic::initializer(20);

int main() {
    ClassStatic a;
    ClassStatic b;
    std::cout << "String in a: " << a.get_str() << std::endl;
    std::cout << "String in b: " << b.get_str() << std::endl;
    a.set_str("I am fine");
    std::cout << "String in a: " << a.get_str() << std::endl;
    std::cout << "String in b: " << b.get_str() << std::endl;
    std::cin.ignore();
}

আউটপুট:

String in a: How are you?
String in b: How are you?
String in a: I am fine
String in b: I am fine

আপনি newকেবল তাত্ক্ষণিকভাবে পয়েন্টারটি ফাঁস করে এটি ওভাররাইট করার জন্য কেন একটি চর অ্যারে যুক্ত করছেন !?
এরিক

0

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

std::call_once()সি ++ 11 এ উপলব্ধ; যদি আপনি এটি ব্যবহার না করতে পারেন তবে এটি একটি স্ট্যাটিক বুলিয়ান ক্লাস-ভেরিয়েবল এবং একটি তুলনা-ও-বিনিময় পারমাণবিক-অপারেশন দিয়ে সম্পন্ন করা যেতে পারে। আপনার কন্সট্রাকটর মধ্যে, আপনি যদি atomically থেকে ক্লাস-স্ট্যাটিক পতাকা পরিবর্তন করতে পারেন দেখতে falseকরতে true, এবং যদি তাই হয়, আপনি স্ট্যাটিক নির্মাণাধীন কোড রান করতে পারেন।

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

সি ++ 11 অনুপস্থিতিতে এই আপনি শুরু করতে হবে।

আপনাকে গাইড করার জন্য এখানে কয়েকটি সিউডোকোড। এটি আপনার শ্রেণীর সংজ্ঞায় রাখুন:

enum EStaticConstructor { kNotRun, kRunning, kDone };
static volatile EStaticConstructor sm_eClass = kNotRun;

এবং এটি আপনার নির্মাণকারীর মধ্যে:

while (sm_eClass == kNotRun)
{
    if (atomic_compare_exchange_weak(&sm_eClass, kNotRun, kRunning))
    {
        /* Perform static initialization here. */

        atomic_thread_fence(memory_order_release);
        sm_eClass = kDone;
    }
}
while (sm_eClass != kDone)
    atomic_pause();
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.