ক্লাস সংজ্ঞায় স্থির দৃ const় পূর্ণসংখ্যার সদস্যদের সংজ্ঞা দেওয়া


109

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

তাহলে, কেন নীচের কোডটি আমাকে একটি লিঙ্কারের ত্রুটি দেয়?

#include <algorithm>
#include <iostream>

class test
{
public:
    static const int N = 10;
};

int main()
{
    std::cout << test::N << "\n";
    std::min(9, test::N);
}

আমি যে ত্রুটি পেয়েছি তা হ'ল:

test.cpp:(.text+0x130): undefined reference to `test::N'
collect2: ld returned 1 exit status

মজার বিষয় হল, আমি যদি কলকে স্ট্যান্ড :: মিনিটে মন্তব্য করি তবে কোডটি সংকলন এবং লিঙ্কগুলি ঠিক জরিমানা (যদিও পরীক্ষা :: এনও পূর্ববর্তী লাইনে রেফারেন্সযুক্ত)।

কি হচ্ছে সম্পর্কে কোন ধারণা?

আমার সংকলকটি লিনাক্সে জিসিসি 4.4।


3
ভিজ্যুয়াল স্টুডিও 2010 এ দুর্দান্ত কাজ করে
কুকুরছানা

4
এই সঠিক ত্রুটিটি gcc.gnu.org/wiki/…
জোনাথন

বিশেষ ক্ষেত্রে char, আপনি এটির পরিবর্তে এটি সংজ্ঞায়িত করতে পারেন constexpr static const char &N = "n"[0];। নোট করুন &। আমার ধারণা এটি কাজ করে কারণ আক্ষরিক স্ট্রিংগুলি স্বয়ংক্রিয়ভাবে সংজ্ঞায়িত হয়। আমি যদিও এ সম্পর্কে উদ্বিগ্ন - এটি বিভিন্ন অনুবাদ ইউনিটের মধ্যে শিরোনামের ফাইলে অদ্ভুত আচরণ করতে পারে কারণ স্ট্রিংটি সম্ভবত একাধিক ভিন্ন ঠিকানায় থাকবে।
অ্যারন ম্যাকডেইড

1
এই প্রশ্নটি "কনস্ট্যান্টদের জন্য # নির্দিষ্টকরণগুলি ব্যবহার করবেন না" এর সি ++ উত্তর এখনও কতটা দরিদ্র তা প্রকাশিত।
জোহানেস ওভারম্যান

1
@ জোহানেস ওভারম্যান এই বিষয়ে, আমি বিশ্বব্যাপী পরিবর্তনশীলগুলির জন্য সি ++ ১ since এর সাথে ইনলাইন ব্যবহারের কথা উল্লেখ করতে চাই inline const int N = 10, যা আমার জ্ঞানের কাছে এখনও লিঙ্কার দ্বারা নির্ধারিত কোথাও স্টোরেজ রয়েছে। শ্রেণি সংজ্ঞা পরীক্ষার অভ্যন্তরে স্থির পরিবর্তনশীল সংজ্ঞা প্রদান করতে কী-ওয়ার্ড ইনলাইনও এই ক্ষেত্রে ব্যবহৃত হতে পারে ।
অল্প বয়স্ক

উত্তর:


72

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

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

http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/cplr038.htm

মজার বিষয় হল, আমি যদি কলকে স্ট্যান্ড :: মিনিটে মন্তব্য করি তবে কোডটি সংকলন এবং লিঙ্কগুলি ঠিক জরিমানা (যদিও পরীক্ষা :: এনও পূর্ববর্তী লাইনে রেফারেন্সযুক্ত)।

কি হচ্ছে সম্পর্কে কোন ধারণা?

স্ট্যান্ড :: মিনিট কনস্টমেন্ট রেফারেন্স দ্বারা এর পরামিতি নেয়। এটি যদি এটিকে মূল্য দিয়ে নিয়ে যায় তবে আপনার এই সমস্যাটি হবে না তবে যেহেতু আপনার রেফারেন্স দরকার আপনার একটি সংজ্ঞাও দরকার।

এখানে অধ্যায় / শ্লোক:

9.4.2 / 4 - যদি কোনও staticডেটা সদস্য constঅবিচ্ছেদ্য বা constগণনার ধরণের হয় তবে শ্রেণীর সংজ্ঞায় এর ঘোষণার ফলে একটি ধ্রুবক- আরম্ভকারী নির্দিষ্ট করা যায় যা একটি অবিচ্ছেদ্য ধ্রুবক অভিব্যক্তি (5.19) হবে। সেক্ষেত্রে সদস্যটি অবিচ্ছেদ্য ধ্রুবক প্রকাশে উপস্থিত হতে পারে। সদস্য যদি প্রোগ্রামে ব্যবহৃত হয় এবং নামপথের স্কোপ সংজ্ঞাটিতে কোনও প্রারম্ভিক অন্তর্ভুক্ত না থাকে তবে সদস্যটির নাম স্পেস স্কোপে এখনও সংজ্ঞায়িত করা হবে

সম্ভাব্য কাজের জন্য চুর উত্তর দেখুন।


আমি দেখছি, এটি আকর্ষণীয়। সেক্ষেত্রে ঘোষণার পয়েন্টে মূল্য প্রদানের তুলনায় সংজ্ঞাটির বিন্দুতে মূল্য সরবরাহের মধ্যে পার্থক্য কী? কোনটি সুপারিশ করা হয়?
হাইকম্যান্ডার 4

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

2
অবিশ্বাস্য উত্তরটি হ'ল স্থির প্রতিস্থাপন x = 1; একটি মূল্যবোধ কিন্তু মূল্য নেই। সংকলনের সময় মানটি ধ্রুবক হিসাবে উপলব্ধ (আপনি এটির সাথে একটি অ্যারের মাত্রা দিতে পারেন) স্ট্যাটিক কনস্ট y; [কোনও প্রারম্ভক নয়] অবশ্যই সিপিপি ফাইলে সংজ্ঞায়িত করা উচিত এবং এটি কোনও মূল্য বা লভালু হিসাবে ব্যবহার করা যেতে পারে।
ডেল উইলসন

2
তারা এটিকে প্রসারিত / উন্নত করতে পারলে ভাল লাগবে। সূচনাযুক্ত-তবে-সংজ্ঞায়িত অবজেক্টগুলিকে, আমার মতে, আক্ষরিকের মতোই আচরণ করা উচিত। উদাহরণস্বরূপ, আমরা একটি আক্ষরিক বাঁধে করার অনুমতি দেওয়া হয় 5একটি থেকে const int&। তাহলে কেন ওপি'র test::Nসাথে সম্পর্কিত আক্ষরিক হিসাবে বিবেচনা করা হবে না ?
অ্যারন ম্যাকডেইড

আকর্ষণীয় ব্যাখ্যা, ধন্যবাদ! এর অর্থ হ'ল সি ++ স্ট্যাটিক কনস্টে এখনও পূর্ণসংখ্যা # ডিফাইনগুলির কোনও প্রতিস্থাপন নেই। এনাম সর্বদা কেবলমাত্র স্বাক্ষরিত থাকে, তাই স্বতন্ত্র ধ্রুবকগুলির জন্য এনাম ক্লাস ব্যবহার করতে হয়। ধ্রুবক সহ ধ্রুবক ঘোষণাপত্রটি অধঃপতিত করা এবং আক্ষরিক ধ্রুবকের কাছে মূল্যবোধ জানার পক্ষে এটি আমার কাছে স্পষ্ট হবে যেহেতু এটি সমস্যা ছাড়াই সংকলন করবে। সি ++ এর অনেক দীর্ঘ পথ রয়েছে ...
জোহানেস ওভারম্যান্ন

51

তার সি ++ এফএকিউতে বাজনার স্ট্রাস্ট্রপের উদাহরণটি আপনাকে সঠিক বলে পরামর্শ দেয় এবং আপনি ঠিকানাটি গ্রহণ করলে কেবল একটি সংজ্ঞা প্রয়োজন।

class AE {
    // ...
public:
    static const int c6 = 7;
    static const int c7 = 31;
};

const int AE::c7;   // definition

int f()
{
    const int* p1 = &AE::c6;    // error: c6 not an lvalue
    const int* p2 = &AE::c7;    // ok
    // ...
}

তিনি বলেছেন "আপনি যদি কোনও স্থির সদস্যের ঠিকানা নিতে পারেন তবে (এবং কেবলমাত্র যদি) এর ক্লাসের বাইরে কোনও সংজ্ঞা থাকে" । যা পরামর্শ দেয় এটি অন্যথায় কাজ করবে। হতে পারে আপনার কমপক্ষে ফাংশনটি কোনওভাবে পর্দার আড়ালে ঠিকানাগুলিকে ডাকবে।


2
std::minরেফারেন্স অনুসারে এর পরামিতি নেয়, এজন্য একটি সংজ্ঞা প্রয়োজন।
Rakete1111

যদি AE একটি টেম্পলেট শ্রেণি AE <ক্লাস টি> এবং সি 7 কোনও ইনট নয় তবে টি :: আকার_ টাইপ হয় তবে আমি সংজ্ঞাটি কীভাবে লিখব? আমার শিরোনামটিতে মানটি "-1" থেকে শুরু হয়েছে তবে ঝাঁকুনি অনির্ধারিত মান বলে এবং সংজ্ঞাটি কীভাবে লিখতে হয় তা আমি জানি না।
ফ্যাবিয়ান

@ ফ্যাবিয়ান আমি ভ্রমণ করছি এবং একটি ফোনে এবং কিছুটা ব্যস্ত ... তবে আমি মনে করব যে আপনার মন্তব্যটি মনে হচ্ছে এটি একটি নতুন প্রশ্ন হিসাবে সবচেয়ে ভাল লেখা হবে। আপনার ত্রুটিটি সহ একটি এমসিভিই লিখুন , সম্ভবত জিসিসি যা বলবে তা নিক্ষেপ করুন। আমি বাজি ধরেছি লোকেরা কী তাড়াতাড়ি আপনাকে বলবে।
হোস্টাইলফোর্ক বলেছেন, এস ই

@ হোস্টাইলফর্ক: এমসিভিই লেখার সময় আপনি কখনও কখনও সমাধানটি নিজেই বের করে ফেলেন। আমার ক্ষেত্রে উত্তরটি রয়েছে template<class K, class V, class C> const typename AE<K,V,C>::KeyContainer::size_type AE<K,V,C>::c7;যেখানে কী কনটেনার স্টাড :: ভেক্টর <কে> এর টাইপডেফ। একজনকে অবশ্যই সমস্ত টেম্পলেট প্যারামিটারগুলি তালিকাবদ্ধ করতে হবে এবং টাইপনেম লিখতে হবে কারণ এটি নির্ভরশীল প্রকার। হতে পারে যে কেউ এই মন্তব্য দরকারী বলে মনে করি। যাইহোক, এখন আমি আশ্চর্য হয়েছি কীভাবে এটি ডিএলএলে রফতানি করতে পারি কারণ টেম্পলেট শ্রেণি অবশ্যই শিরোনামে থাকে। আমার কি সি 7 রফতানি করা দরকার?
ফ্যাবিয়ান

24

এটি করার আরেকটি উপায়, যাইহোক যাইহোক পূর্ণসংখ্যার ধরণের জন্য, ক্লাসে এনাম্ট হিসাবে ধ্রুবককে সংজ্ঞায়িত করা:

class test
{
public:
    enum { N = 10 };
};

2
এবং এটি সম্ভবত সমস্যার সমাধান করবে। যখন মিনিট () এর জন্য প্যারামিটার হিসাবে এন ব্যবহার করা হয় তখন এটি সম্ভবত একটি বিদ্যমান ভেরিয়েবল উল্লেখ করার পরিবর্তে একটি অস্থায়ী তৈরির কারণ হবে।
এডওয়ার্ড স্ট্রেঞ্জ

এটির সুবিধাটি ছিল যে এটি ব্যক্তিগত করা যেতে পারে।
অ্যাগোস্টিনো

11

শুধু ইন এর নয়। তবে আপনি শ্রেণির ঘোষণায় মানটি নির্ধারণ করতে পারবেন না। যদি তোমার থাকে:

class classname
{
    public:
       static int const N;
}

.h ফাইলটিতে আপনার অবশ্যই থাকতে হবে:

int const classname::N = 10;

.cpp ফাইল এ।


2
আমি সচেতন যে আপনি ক্লাস ঘোষণার ভিতরে যে কোনও ধরণের ভেরিয়েবল ঘোষণা করতে পারেন declare আমি বলেছিলাম যে আমি স্থির পূর্ণসংখ্যার ধ্রুবকগুলি শ্রেণির ঘোষণার ভিতরেও সংজ্ঞায়িত হতে পারি । এটা কি না? যদি তা না হয় তবে কেন এটি সংকলকটি যেখানে ক্লাসের ভিতরে এটি সংজ্ঞায়িত করার চেষ্টা করি সেদিকে কোনও ত্রুটি দেয় না? তদুপরি, কেন std :: cout লাইন কোনও লিঙ্কারের ত্রুটি সৃষ্টি করে না, তবে এসটিডি :: মিনিট লাইনটি করে?
হাইকম্যান্ডার 4

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

@ হাইকম্যান্ডার ৪: আপনি static constক্লাস সংজ্ঞাতে অবিচ্ছেদ্য সদস্যের জন্য একটি প্রাথমিক পাঠক সরবরাহ করতে পারেন । কিন্তু এটি এখনও সেই সদস্যকে সংজ্ঞায়িত করে না । বিস্তারিত জানতে নোয়া রবার্টসের উত্তর দেখুন।
এএনটি

9

সমস্যাটি ঘিরে কাজ করার আরও একটি উপায় এখানে রয়েছে:

std::min(9, int(test::N));

(আমি মনে করি ক্রেজি এডির উত্তরটি সমস্যাটি কেন বিদ্যমান তা সঠিকভাবে বর্ণনা করে))


5
বা এমনকিstd::min(9, +test::N);
টমিলভ আনাতোলি

এখানে যদিও বড় প্রশ্ন: এই সব কি সর্বোত্তম? আমি আপনাকে বলছি না, তবে সংজ্ঞাটি এড়িয়ে যাওয়ার ক্ষেত্রে আমার বড় আকর্ষণটি হ'ল কনস্টিক স্ট্যাটিকটি ব্যবহার করার জন্য এটি কোনও স্মৃতি এবং কোনও ওভারহেড গ্রহণ করা উচিত নয়।
অপাক্স

6

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

static constexpr int N = 10;

এটি তাত্ত্বিকভাবে এখনও আপনার একটি .cpp ফাইলে ধ্রুবক সংজ্ঞায়িত করা প্রয়োজন, তবে যতক্ষণ না আপনি Nএটির ঠিকানা নেন না এটি কোনও সংকলক প্রয়োগকারী একটি ত্রুটি সৃষ্টি করে এমন সম্ভাবনা খুব কমই থাকে;)।


এবং উদাহরণস্বরূপ 'কনস্ট ইন্ট এন্ড' টাইপের আর্গুমেন্ট হিসাবে যদি মানটি পাস করতে হয় তবে কী হবে? :-)
Wormer

এটা ঠিক কাজ করে। আপনি N কে সেভাবে ইনস্ট্যান্ট করছেন না , কেবলমাত্র একটি অস্থায়ী সম্পর্কে একটি রেফারেন্স রেফারেন্সটি প্রেরণ করছেন। wandbox.org/perMLink/JWeyXwrVRvsn9cBj
কার্লো উড

সি ++ ১ maybe হতে পারে, সি ++ ১৪ নয়, এমনকি জিসিসি 6.3.0 এবং এর আগের সংস্করণগুলিতেও সি ++ 17 নয়, এটি কোনও স্ট্যান্ডার্ড জিনিস নয়। তবে এটি উল্লেখ করার জন্য ধন্যবাদ।
কৃষক

হ্যাঁ, আপনি ঠিক বলেছেন। আমি ভ্যান্ডবক্সে সি ++ 14 চেষ্টা করিনি। ওহ ভাল, এটি সেই অংশ যেখানে আমি বলেছিলাম "এই তাত্ত্বিকভাবে এখনও আপনার ধ্রুবকটি সংজ্ঞায়িত করা প্রয়োজন"। সুতরাং, আপনি ঠিক বলেছেন যে এটি 'স্ট্যান্ডার্ড' নয়।
কার্লো উড

3

সি ++ স্ট্যাটিক কনস্টের সদস্যদের একটি শ্রেণির মধ্যে সংজ্ঞায়িত করতে দেয়

নাপ, ৩.১ §২ বলেছেন:

একটি ঘোষণাকে একটি সংজ্ঞা বলা হয় যতক্ষণ না এটি ফাংশনটির বডি (8.4) নির্দিষ্ট না করে কোনও ফাংশন ঘোষণা করে না, এতে বাহ্যিক নির্দিষ্টকরণকারী (7.1.1) বা লিঙ্কেজ-স্পেসিফিকেশন (7.5) থাকে না এবং কোনও আরম্ভকারী বা কোনও কার্যকরী ব্যক্তি থাকে না, এটি একটি স্ট্যাটিক ডেটা ঘোষণা করে শ্রেণীর সংজ্ঞা (9.4) এর সদস্য , এটি একটি শ্রেণীর নাম ঘোষণা (9.1), এটি একটি অস্বচ্ছ-এনাম-ডিক্লেয়ারেশন (7.2), অথবা এটি টাইপডেফ ঘোষণা (7.1.3), ব্যবহার-ঘোষণা (7.3)। 3), বা একটি ব্যবহার-নির্দেশিকা (7.3.4)।

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