সি ++ 11 অ স্থিতিশীল এবং নন-কনস্ট্যান্ট সদস্যদের শ্রেণিকেন্দ্রিককরণের অনুমতি দেয়। কী বদলে গেল?


89

সি ++ 11 এর আগে আমরা কেবলমাত্র অবিচ্ছেদ্য বা গণনা প্রকারের স্ট্যাটিক কনস্ট সদস্যদের উপর শ্রেণি সূচনা করতে পারি। স্ট্রাস্ট্রাপ তার সি ++ এফএকিউতে এটি আলোচনা করে নিম্নলিখিত উদাহরণটি দিয়েছেন:

class Y {
  const int c3 = 7;           // error: not static
  static int c4 = 7;          // error: not const
  static const float c5 = 7;  // error: not integral
};

এবং নিম্নলিখিত যুক্তি:

তাহলে এই অসুবিধাগুলি বিধিনিষেধ কেন বিদ্যমান? একটি শ্রেণি সাধারণত একটি শিরোনাম ফাইলে ঘোষিত হয় এবং একটি শিরোনাম ফাইল সাধারণত অনেক অনুবাদ ইউনিটে অন্তর্ভুক্ত থাকে। তবে জটিল লিঙ্কারের নিয়মগুলি এড়াতে, সি ++ এর প্রয়োজন প্রতিটি বস্তুর একটি অনন্য সংজ্ঞা রয়েছে। এই নিয়মটি ভঙ্গ করা হবে যদি সি ++ সত্তাগুলির বস্তুগুলির হিসাবে মেমোরিতে সঞ্চয় করা দরকার সত্তাগুলির শ্রেণিবদ্ধ সংজ্ঞা মঞ্জুরি দেয়।

যাইহোক, সি ++ 11 এই বিধিনিষেধগুলি শিথিল করে, অ স্থিতিশীল সদস্যদের (-12.6.2 / 8) শ্রেণিতে শুরুর অনুমতি দেয়:

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

  • সত্তা যদি কোনও অ-স্থিতিশীল ডেটা সদস্য হয় যার একটি ব্রেস-বা-সম-ইনিশিয়ালাইজার থাকে , সত্তাটি 8.5 -তে বর্ণিত হিসাবে শুরু করা হয়;
  • অন্যথায়, সত্তা যদি একটি বৈকল্পিক সদস্য হয় (9.5), কোনও আরম্ভ করা হয় না;
  • অন্যথায়, সত্তাটি ডিফল্ট-ইনিশিয়ালড (8.5)।

বিভাগ 9.4.2 এছাড়াও constexprনির্দিষ্ট -স্থির সদস্যদের স্পেসিফায়ারের সাথে চিহ্নিত করা হলে শ্রেণিকেন্দ্রিক সূচনার অনুমতি দেয় ।

তাহলে আমাদের C ++ 03 এ থাকা বিধিনিষেধের কারণগুলির কী হয়েছিল? আমরা কি কেবল "জটিল লিঙ্কার বিধিগুলি" গ্রহণ করি বা অন্য কিছু পরিবর্তন করেছি যা এটি কার্যকর করা সহজ করে তোলে?


4
কিছুই ঘটেনি. কেবলমাত্র এই সমস্ত শিরোলেখ-টেম্পলেটগুলির সাথে কম্পাইলাররা বুদ্ধিমান হয়ে উঠেছে যাতে এখন তুলনামূলকভাবে সহজ এক্সটেনশন is
Öö তিব

আকর্ষণীয়ভাবে আমার আইডিইতে যথেষ্ট যখন আমি সি সি ++ ১১ টি প্রাক সংকলন নির্বাচন করি তখন আমাকে অ স্থিতিশীল কনস্ট্যান্ট অবিচ্ছেদ্য সদস্যদের আরম্ভ করার অনুমতি দেওয়া হয়
ডিন পি

উত্তর:


67

সংক্ষিপ্ত উত্তরটি হ'ল তারা লিঙ্কারটিকে একই রকম রাখে, কম্পাইলারটিকে আগের চেয়ে আরও জটিল করে তোলার ব্যয়ে at

উদাহরণস্বরূপ, লিঙ্কারের জন্য বাছাইয়ের জন্য একাধিক সংজ্ঞা তৈরির পরিবর্তে এটি কেবলমাত্র একটি সংজ্ঞায় ফলাফল দেয় এবং সংকলকটিকে এটি বাছাই করতে হবে।

এটি প্রোগ্রামারকে পাশাপাশি বাছাই করতে আরও কিছু জটিল নিয়ম বাড়ে , তবে এটি বেশিরভাগই সহজ যে এটি কোনও বড় বিষয় নয় deal যখন আপনার একক সদস্যের জন্য আলাদা আলাদা দুটি সূচনা নির্দিষ্ট করা থাকে তখন অতিরিক্ত বিধিগুলি আসে:

class X { 
    int a = 1234;
public:
    X() = default;
    X(int z) : a(z) {}
};

এখন, এই সময়ে অতিরিক্ত নিয়মগুলি aযখন আপনি অ-ডিফল্ট কনস্ট্রাক্টর ব্যবহার করেন তখন আরম্ভ করার জন্য কোন মানটি ব্যবহৃত হয় । এর উত্তরটি মোটামুটি সহজ: আপনি যদি এমন কোনও কনস্ট্রাক্টর ব্যবহার করেন যা অন্য কোনও মান নির্দিষ্ট করে না, তবে এটি 1234আরম্ভ করার জন্য ব্যবহৃত হবে a- তবে আপনি যদি এমন কোনও কনস্ট্রাক্টর ব্যবহার করেন যা অন্য কোনও মান নির্দিষ্ট করে, তবে 1234মূলত এড়ানো হবে।

উদাহরণ স্বরূপ:

#include <iostream>

class X { 
    int a = 1234;
public:
    X() = default;
    X(int z) : a(z) {}

    friend std::ostream &operator<<(std::ostream &os, X const &x) { 
        return os << x.a;
    }
};

int main() { 
    X x;
    X y{5678};

    std::cout << x << "\n" << y;
    return 0;
}

ফলাফল:

1234
5678

4
মনে হয় এর আগেও বেশ সম্ভব ছিল। এটি কেবল একটি সংকলক লেখার কাজকে আরও শক্ত করে তুলেছে। এটা কি ন্যায্য বক্তব্য?
allyourcode

10
@allyourcode: হ্যাঁ এবং না হ্যাঁ, এটি সংকলক লেখা আরও শক্ত করে তুলেছে। তবে না, কারণ এটি সি ++ স্পেসিফিকেশন লেখার বিষয়টিও বেশ কিছুটা শক্ত করে তুলেছে।
জেরি কফিন

শ্রেণীর সদস্যকে কীভাবে আরম্ভ করতে হবে তার কোনও পার্থক্য রয়েছে: int x = 7; বা int x {7} ;?
এমবারোস

9

আমার ধারণা, টেমপ্লেটগুলি চূড়ান্ত হওয়ার আগে যুক্তিটি লেখা হতে পারে। টেমপ্লেটগুলির স্থির সদস্যদের সমর্থন করার জন্য স্থিতিশীল সদস্যদের ইন-ক্লাস ইনিশিয়ালাইজারদের জন্য প্রয়োজনীয় সমস্ত "জটিল লিঙ্কার বিধি (গুলি)" এর পরেও সি ++ 11 এর জন্য ইতিমধ্যে প্রয়োজনীয় ছিল / ছিল।

বিবেচনা

struct A { static int s = ::ComputeSomething(); }; // NOTE: This isn't even allowed,
                                                   // thanks @Kapil for pointing that out

// vs.

template <class T>
struct B { static int s; }

template <class T>
int B<T>::s = ::ComputeSomething();

// or

template <class T>
void Foo()
{
    static int s = ::ComputeSomething();
    s++;
    std::cout << s << "\n";
}

তিনটি ক্ষেত্রেই সংকলকটির সমস্যা একই: কোন অনুবাদ-ইউনিটে এটির সংজ্ঞা sএবং কোডটি শুরু করার জন্য প্রয়োজনীয় কোডটি নির্গত করা উচিত ? সহজ সমাধান হ'ল এটিকে সর্বত্র নির্গত করা এবং লিঙ্কারটিকে এটিকে সাজিয়ে নেওয়া দিন। এই কারণেই লিঙ্কাররা ইতিমধ্যে পছন্দ মতো জিনিসগুলিকে সমর্থন করে __declspec(selectany)। এটি ছাড়া C ++ 03 বাস্তবায়ন করা সম্ভব হত না। এবং এজন্যই লিঙ্কারটি প্রসারিত করার প্রয়োজন ছিল না।

এটিকে আরও কথায় কথায় বলতে: আমি মনে করি যে পুরানো স্ট্যান্ডার্ডে দেওয়া যুক্তিটি কেবল সাধারণ ভুল।


হালনাগাদ

কপিল যেভাবে উল্লেখ করেছেন, আমার প্রথম উদাহরণটি বর্তমান মানের (সি ++ 14) এও অনুমোদিত নয়। আমি যাহাই হউক না কেন, কারণ এটি বাস্তবায়ন (সংকলক, লিঙ্কার) এর সবচেয়ে কঠিন কেস আইএমও। আমার বিন্দু: এমনকি যে ক্ষেত্রে কোন কঠিন কি ইতিমধ্যে যেমন অনুমোদিত যখন টেমপ্লেট ব্যবহার না করে নয়।


লজ্জাজনকভাবে এটি কোনও আপব্যাটস পেল না, কারণ অনেকগুলি সি ++ 11 বৈশিষ্ট্য সমান যে সংকলকগণ ইতিমধ্যে প্রয়োজনীয় দক্ষতা বা অনুকূলকরণ অন্তর্ভুক্ত করেছেন।
অ্যালেক্স কোর্ট

@ অ্যালেক্সকোর্ট আমি সম্প্রতি এই উত্তরটি লিখেছি। প্রশ্ন এবং জেরির উত্তর 2012 থেকে যদিও। সুতরাং আমি অনুমান করি যে কেন আমার উত্তরটি তেমন মনোযোগ পেল না।
পল গ্রোকে

4
এটি "স্ট্রাক্ট এ {স্ট্যাটিক ইন্ট এস = :: কমপিউটসোমিংথিং (); comp" এর প্রশংসা করবে না কারণ কেবল স্ট্যাটিক
কনস্টের

8

তত্ত্বগত So why do these inconvenient restrictions exist?...কারণে বৈধ তবে এটি সহজেই বাইপাস করা যায় এবং সি ++ 11 ঠিক এটি করে।

আপনি যখন কোনও ফাইল অন্তর্ভুক্ত করেন তখন এটিতে কেবল ফাইল অন্তর্ভুক্ত থাকে এবং কোনও সূচনা উপেক্ষা করে। আপনি যখন ক্লাসটি ইনস্ট্যান্ট করবেন কেবল তখনই সদস্যদের আরম্ভ করা হয় ।

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

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

এটি C ++ 11 এ স্ট্রস্ট্রাপের নিজস্ব FAQ থেকে স্পষ্ট ।


পুনরায় "যদি কনস্ট্রাক্টরকে না ডাকা হয়, মানগুলি আরম্ভ হয় না": আমি কীভাবে Y::c3প্রশ্নটির সদস্য ইনিশিয়ালাইজেশনকে বাধা দিতে পারি ? আমি এটি যেমন বুঝতে পেরেছি, c3ততক্ষণ সর্বদা আরম্ভ করা হবে যদি না এমন কোনও কনস্ট্রাক্টর থাকে যা ঘোষণায় প্রদত্ত ডিফল্টটিকে ওভাররাইড করে।
পিটার - মনিকা পুনরায়
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.