ক্লাসের মধ্যে এনাম ঘোষণা করা


150

নিম্নলিখিত কোড স্নিপেটে Colorএনামের Carপরিধি সীমাবদ্ধ করার জন্য এবং বিশ্বব্যাপী নেমস্পেসকে "দূষিত" না করার চেষ্টা করার জন্য এনামকে শ্রেণীর মধ্যে ঘোষণা করা হয়েছে ।

class Car
{
public:

   enum Color
   {
      RED,
      BLUE,
      WHITE
   };

   void SetColor( Car::Color color )
   {
      _color = color;
   }

   Car::Color GetColor() const
   {
      return _color;
   }

private:

   Car::Color _color;

};

(1) Colorএনামের সুযোগ সীমাবদ্ধ করার এটি কি ভাল উপায় ? বা, আমি কি এটি Carক্লাসের বাইরে ঘোষণা করতে পারি , তবে সম্ভবত এটির নিজস্ব নামস্থান বা কাঠামোর মধ্যে থাকতে পারে? : আমি শুধুমাত্র এই নিবন্ধটি আজ, যা আধুনিক অত্যাবশ্যক এবং আলোচনা enums সম্পর্কে কিছু চমৎকার পয়েন্ট জুড়ে এসেছিল http://gamesfromwithin.com/stupid-c-tricks-2-better-enums

(২) এই উদাহরণে, ক্লাসের মধ্যে কাজ করার সময়, এনামকে কোড করা ভাল Car::Color, বা কেবল Colorযথেষ্ট হবে? (আমি ধরে নিলাম যে Colorপূর্বেরটি আরও ভাল, কেবলমাত্র যদি বিশ্বব্যাপী নেমস্পেসে আরও একটি এনাম ঘোষণা করা হয় That সেইভাবে , কমপক্ষে, আমরা যে এনামটি উল্লেখ করছি সে সম্পর্কে আমরা স্পষ্ট are

উত্তর:


85
  1. যদি Colorএমন কিছু হয় যা সুনির্দিষ্টভাবে সুনির্দিষ্ট হয় Carতবে সেই উপায়টিই আপনি তার ব্যাপ্তি সীমাবদ্ধ করবেন। যদি আপনি Colorঅন্য একটি ক্লাস ব্যবহার করেন যা অন্যান্য ক্লাসগুলি ব্যবহার করে তবে আপনি এটি বিশ্বব্যাপীও তৈরি করতে পারেন (বা কমপক্ষে বাইরেও Car)।

  2. এতে কোন পার্থক্য নেই. যদি কোনও বিশ্বব্যাপী থাকে তবে স্থানীয় একটি এখনও যেভাবেই ব্যবহৃত হয় কারণ এটি বর্তমান সুযোগের কাছাকাছি রয়েছে। নোট করুন যে আপনি যদি শ্রেণীর সংজ্ঞার বাইরে সেই ফাংশনটি সংজ্ঞায়িত করেন তবে আপনাকে Car::Colorফাংশনের ইন্টারফেসে স্পষ্টভাবে নির্দিষ্ট করতে হবে ।


12
2. হ্যাঁ এবং না। Car::Color getColor()তবে void Car::setColor(Color c)কারণ আমাদের মধ্যে setColorইতিমধ্যে নির্দিষ্টকরণকারক রয়েছে।
ম্যাথিউ এম।

84

আজকাল - সি ++ 11 ব্যবহার করে - আপনি এটির জন্য এনাম ক্লাস ব্যবহার করতে পারেন :

enum class Color { RED, BLUE, WHITE };

এএফএআই এটি যা চায় ঠিক তাই করে।


2
দুঃখের বিষয়, এটি সদস্যের ফাংশনগুলিকে অনুমতি দেয় না: stackoverflow.com/a/53284026/7395227
Andreas

66

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

struct Color
{
    enum Type
    {
        Red, Green, Black
    };
    Type t_;
    Color(Type t) : t_(t) {}
    operator Type () const {return t_;}
private:
   //prevent automatic conversion for any other built-in types such as bool, int, etc
   template<typename T>
    operator T () const;
};

ব্যবহার:

Color c = Color::Red;
switch(c)
{
   case Color::Red:
     //некоторый код
   break;
}
Color2 c2 = Color2::Green;
c2 = c; //error
c2 = 3; //error
if (c2 == Color::Red ) {} //error
If (c2) {} error

আমি ব্যবহারের সুবিধার্থে ম্যাক্রো তৈরি করেছি:

#define DEFINE_SIMPLE_ENUM(EnumName, seq) \
struct EnumName {\
   enum type \
   { \
      BOOST_PP_SEQ_FOR_EACH_I(DEFINE_SIMPLE_ENUM_VAL, EnumName, seq)\
   }; \
   type v; \
   EnumName(type v) : v(v) {} \
   operator type() const {return v;} \
private: \
    template<typename T> \
    operator T () const;};\

#define DEFINE_SIMPLE_ENUM_VAL(r, data, i, record) \
    BOOST_PP_TUPLE_ELEM(2, 0, record) = BOOST_PP_TUPLE_ELEM(2, 1, record),

ব্যবহার:

DEFINE_SIMPLE_ENUM(Color,
             ((Red, 1))
             ((Green, 3))
             )

কিছু তথ্যসূত্র:

  1. ভেষজ সুটার, জুম হিসলপ, সি / সি ++ ব্যবহারকারী জার্নাল, 22 (5), মে 2004
  2. ভেষজ সুটার, ডেভিড ই মিলার, বজর্ন স্ট্রস্ট্রপ স্ট্রংলি টাইপড এনামস (পুনর্বিবেচনা 3), জুলাই 2007

আমি এই পছন্দ। এটি এনামকে বৈধ মান দিয়ে তাত্ক্ষণিকভাবে বাধ্য করতে বাধ্য করে। আমি মনে করি একটি অ্যাসাইনমেন্ট অপারেটর এবং অনুলিপি নির্মাণকারী কার্যকর হবে। এছাড়াও টি_র ব্যক্তিগত থাকতে হবে। ম্যাক্রোগুলি আমি ছাড়া করতে পারি।
jmucchiello

আমিও এটি পছন্দ করি রেফারেন্সের জন্য ধন্যবাদ।
anio

1
আপনি বলেছিলেন: "এছাড়াও এটি আরও অনেক ধরণের টাইপসেফ (আপনি দুটি পৃথক গণনা নির্ধারণ ও তুলনা করতে পারবেন না ..." । আপনি কেন এটি একটি ভাল বৈশিষ্ট্য বলে মনে করেন? আমি মনে করি if(c2 == Color::Red )যুক্তিযুক্ত এবং অবশ্যই সংকলন করা উচিত তবে আপনার উদাহরণে এটি এটি নিয়োগের ক্ষেত্রেও একই যুক্তি!
নওয়াজ

3
@ নাওয়াজ c2অন্য ধরণের ( Color2), তাই আপনি কেন মনে করেন c2 == Color::Redএবং অ্যাসাইনমেন্টগুলি সংকলন করা উচিত? যদি Color::Red1 হয়, এবং Color2::Red2 হয়? করা উচিত Color::Red == Color2::Redমূল্যায়ন trueবা false? আপনি যদি নন-টাইপসেট এনফিউরেটরগুলি মিশ্রণ করেন তবে আপনার খারাপ সময় হবে।
ভিক্টর কে

2
কেন t_ টাইপ করুন; ব্যক্তিগত?
জিঙ্গাম

7

সাধারণভাবে, আমি সবসময় আমার এনামগুলিকে একটি তে রাখি struct। আমি "উপসর্গ" সহ বেশ কয়েকটি গাইডলাইন দেখেছি।

enum Color
{
  Clr_Red,
  Clr_Yellow,
  Clr_Blue,
};

সর্বদা ভেবেছিল এটিকে Cনির্দেশিকাগুলির চেয়ে আরও বেশি দিকনির্দেশের মতো দেখাচ্ছে C++(সংক্ষিপ্তসার কারণে এবং নামের জায়গাগুলির কারণেও C++)।

সুতরাং সুযোগ সীমিত করতে আমাদের কাছে এখন দুটি বিকল্প রয়েছে:

  • নামব্যবধান
  • structs মধ্যে / শ্রেণীর

আমি ব্যক্তিগতভাবে একটি ব্যবহার করার প্রবণতা রাখি structকারণ এটি টেমপ্লেট প্রোগ্রামিংয়ের পরামিতি হিসাবে ব্যবহার করা যেতে পারে যখন একটি নেমস্পেসটি ম্যানিপুলেট করা যায় না।

কারসাজির উদাহরণগুলির মধ্যে রয়েছে:

template <class T>
size_t number() { /**/ }

যা স্ট্রাক্টের ভিতরে এনামের উপাদানগুলির সংখ্যা প্রদান করে T:)


3

আপনি যদি কোনও কোড লাইব্রেরি তৈরি করে থাকেন তবে আমি নেমস্পেসটি ব্যবহার করব। তবে, এখনও সেই নেমস্পেসের মধ্যে কেবল একটি রঙিন এনাম থাকতে পারেন। আপনার যদি এমন এনামের প্রয়োজন হয় যা একটি সাধারণ নাম ব্যবহার করতে পারে তবে বিভিন্ন শ্রেণীর জন্য বিভিন্ন ধ্রুবক থাকতে পারে তবে আপনার পদ্ধতির ব্যবহার করুন use

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