কেন "নেমস্পেস এক্স ব্যবহার করা হয়;" শ্রেণি / কাঠামো স্তরের ভিতরে অনুমোদিত নয়?


90
class C {
  using namespace std;  // error
};
namespace N {
  using namespace std; // ok
}
int main () {
  using namespace std; // ok
}

সম্পাদনা করুন : এর পিছনে অনুপ্রেরণা জানতে চান।


4
@pst: সি # এর মতো কিছু নেই using namespace। সি # তেমন কিছু মঞ্জুরি দেয় তবে কেবল ফাইল স্কোপে। সি ++ এর using namespaceসাহায্যে আপনি একটি নামের স্থানকে অন্যটিতে অন্তর্ভুক্ত করতে পারবেন।
বিলি ওনিল


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

@iammilind টিবিএইচ কম যত্ন করতে পারে না। আজকের দিনগুলিতে একটি গোলযোগ রয়েছে। তবে একটি পোস্ট চিহ্নিত করে যা "আমি ঠিক জানি না" দিয়ে শুরু হয় ঠিক উত্তর হিসাবে "আরও উদ্দেশ্যমূলক উত্তর এবং আদর্শের রেফারেন্স" রয়েছে। হা হা।
Zach

@ জ্যাকসও, আমি কেবল গৃহীত উত্তর সম্পর্কেই বলছিলাম না, তবে সামগ্রিক পোস্ট। হ্যাঁ এটি উদ্দেশ্যমূলক তবে মান উত্তরটি এই উত্তরে অন্তর্ভুক্ত রয়েছে । এটি "আমি জানি না" দিয়ে শুরু হয়, কারণ এমনকি স্ট্যান্ডার্ডেও কেন "নেমস্পেস" ব্যবহারের অনুমতি দেওয়া হচ্ছে না তা ন্যায়সঙ্গত নয় class/struct। এটি কেবল সহজভাবে অনুমোদিত নয়। তবে গৃহীত উত্তরটি এটিকে অস্বীকার করার জন্য খুব যৌক্তিক যুক্তি নিয়ে আলোচনা করে। অর্থাত্ কোথায় বিবেচনা করতে হবে Hello::Worldএবং কোথায় বিবেচনা করতে হবে World। আশা যে সন্দেহ মুছে।
iammilind

উত্তর:


36

আমি ঠিক জানি না, তবে আমার ধারণা বর্গক্ষেত্রে এটিকে অনুমতি দেওয়া বিভ্রান্তির কারণ হতে পারে:

namespace Hello
{
    typedef int World;
}

class Blah
{
    using namespace Hello;
public:
    World DoSomething();
}

//Should this be just World or Hello::World ?
World Blah::DoSomething()
{
    //Is the using namespace valid in here?
}

যেহেতু এটি করার কোনও সুস্পষ্ট উপায় নেই, স্ট্যান্ডার্ডটি বলে যে আপনি পারবেন না।

এখন, যখন আমরা নেমস্পেসের স্কোপগুলিতে কথা বলছি তখন এটি কম বিভ্রান্তির কারণ:

namespace Hello
{
    typedef int World;
}

namespace Other
{
    using namespace Hello;
    World DoSomething();
}

//We are outside of any namespace, so we have to fully qualify everything. Therefore either of these are correct:

//Hello was imported into Other, so everything that was in Hello is also in Other. Therefore this is okay:
Other::World Other::DoSomething()
{
    //We're outside of a namespace; obviously the using namespace doesn't apply here.
    //EDIT: Apparently I was wrong about that... see comments. 
}

//The original type was Hello::World, so this is okay too.
Hello::World Other::DoSomething()
{
    //Ditto
}

namespace Other
{
    //namespace Hello has been imported into Other, and we are inside Other, so therefore we never need to qualify anything from Hello.
    //Therefore this is unambiguiously right
    World DoSomething()
    {
        //We're inside the namespace, obviously the using namespace does apply here.
    }
}

4
+1, আমি এই কারণটি ভেবেছিলাম, তবে তারপরে একই জিনিস using namespace Hello;অন্যান্য অভ্যন্তরের namespaceজন্যও প্রযোজ্য (এবং এর externঅভ্যন্তরে ফাংশন ঘোষণা করে)।
iammilind

10
আমি এর বিভ্রান্তি মনে করি না। সি ++ অনুমানের কাজ সম্পর্কে নয়। যদি এটি অনুমোদিত হয়, তবে সি ++ আইএসও কমিটি ভাষা নির্দিষ্টকরণে নির্দিষ্ট করে দিত। তাহলে আপনি এটি বিভ্রান্তিকর বলবেন না। অন্যথায় কেউ বলতে পারে এমনকি এটি বিভ্রান্তিকর: আদর্শ one.com/npOeD ... তবে তারপরে এই জাতীয় কোডিংয়ের নিয়মটি নির্দিষ্ট করে দেওয়া হয়েছে।
নওয়াজ

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

6
প্রথম উদাহরণে এটি হওয়া উচিত: Hello::World Blah::DoSomething()বা Blah::World Blah::DoSomething()(যদি এটি অনুমোদিত হয়ে থাকে) তবে সদস্য ফাংশন সংজ্ঞার ফেরতের ধরণটি ভাষাতে শ্রেণীর পরিসর হিসাবে বিবেচিত হয় না, তাই এটি যোগ্য হতে হবে। শ্রেণীর সুযোগের usingসাথে প্রতিস্থাপনের বৈধ উদাহরণ বিবেচনা করুন typedef Hello::World World;। সুতরাং সেখানে কোনও আশ্চর্য হওয়া উচিত নয়।
ডেভিড রদ্রিগেজ - ড্রিবিস

4
যদি এটি অনুমোদিত হয় তবে আমি বিশ্বাস করি যে এটি একটি লেজিক স্কোপ স্তরে প্রয়োগ করা হবে। আমি মনে করি এটি হ'ল কার্যত কোনও আশ্চর্য ছাড়াই "সুস্পষ্ট" সমাধান।
টমাস এডিং

20

কারণ সি ++ স্ট্যান্ডার্ড এটি পরিষ্কারভাবে নিষেধ করে। সি ++ 03 §7.3.4 থেকে [নেমস্পেস.উডির]:

ব্যবহার-নির্দেশিকা :
    নেমস্পেস ব্যবহার করে :: opt  नेস্টেড-নেম-স্পেসিফায়ার অপ্ট  নেমস্পেস-নাম ;

একটি ব্যবহারের নির্দেশিকা শ্রেণীর স্কোপগুলিতে উপস্থিত হবে না তবে এটি নামস্থান স্কোপ বা ব্লক স্কোপে প্রদর্শিত হতে পারে। [দ্রষ্টব্য: কোনও ব্যবহার-নির্দেশিকায় নেমস্পেস-নাম সন্ধান করার সময়, কেবলমাত্র স্থানের নাম বিবেচনা করা হয়, দেখুন 3.4.6। ]

সি ++ স্ট্যান্ডার্ড কেন এটি নিষিদ্ধ করে? আমি জানি না, আইএসও কমিটির কোনও সদস্যকে জিজ্ঞাসা করুন যা ভাষার মান অনুমোদন করেছে।


47
তবুও আরও একটি প্রযুক্তিগতভাবে সঠিক তবে অকেজো উত্তর; সবচেয়ে খারাপ ধরনের। 1) কেবল কমিটির চেয়ে বেশি লোক উত্তর জানেন। ২) কমিটির সদস্যগণ এসওতে অংশ নেন ৩) যদি আপনি উত্তরটি জানেন না (প্রশ্নের চেতনা প্রদত্ত) তবে কেন উত্তর দেওয়া হবে না?
ক্যাটসকুল 3'18

7
@ ক্যাটসকুল: এটি কোনও অকেজো উত্তর নয়। এটি জেনে রাখা খুব কার্যকর যে মানকটি স্পষ্টভাবে এটিকে সম্বোধন করে এবং এটিকে নিষিদ্ধ করে। এটি বিদ্রূপজনক যে সর্বাধিক উত্সাহিত উত্তরটি "আমি ঠিক জানি না" দিয়ে শুরু হয়। এছাড়াও, "স্ট্যান্ডার্ড এটিকে নিষেধ করে" "এটি অনুমোদিত নয় কারণ সংকলক এটি অনুমতি দেয় না", কারণ পরবর্তী ঘটনাটি ফলো-আপ প্রশ্নের উত্তর দেয় না যেমন: এটি কি আমার সংকলকটিতে সমস্যা? সংকলকটি কি স্ট্যান্ডার্ড-কমপ্লায়েন্ট নয়? এটি কি অন্য কিছু বিষয়গুলির একটি পার্শ্ব প্রতিক্রিয়া যা আমি অবগত নই? ইত্যাদি
এন্টোনোন

9

আমি বিশ্বাস করি যে যুক্তিটি সম্ভবত এটি বিভ্রান্তিকর হবে। বর্তমানে, ক্লাস স্তর সনাক্তকারীকে প্রক্রিয়া করার সময়, অনুসন্ধান প্রথমে শ্রেণীর ক্ষেত্র এবং তারপরে ঘেরের নামস্থানতে অনুসন্ধান করবে। using namespaceশ্রেণি পর্যায়ে অনুমতি দেওয়া এখন কীভাবে প্রদর্শন করা হয় তার বেশ কিছু পার্শ্ব প্রতিক্রিয়া থাকতে পারে। বিশেষত, নির্দিষ্ট শ্রেণির ক্ষেত্রটি পরীক্ষা করা এবং ঘেরের নামস্থান পরীক্ষা করার মধ্যে এটির মাঝে মাঝে সঞ্চালন করতে হবে। এটি হ'ল: 1) বর্গ স্তর এবং ব্যবহৃত নেমস্পেস স্তরের লুকোচুয়ালগুলি মার্জ করুন, ২) বর্গক্ষেত্রের পরে ব্যবহৃত নেমস্পেসটি অনুসন্ধান করুন তবে অন্য কোনও শ্রেণির ক্ষেত্রের আগে, 3) বদ্ধ নামকরণের ঠিক আগে ব্যবহৃত নেমস্পেসটি অনুসন্ধান করুন। 4) লুকোচুরিটি এনকোলেসিং নেমস্পেসের সাথে একত্রিত করা হয়েছে।

  1. এটি একটি বড় পার্থক্য করতে পারে, যেখানে শ্রেণি পর্যায়ে কোনও শনাক্তকারী সংলগ্ন নেমস্পেসের কোনও শনাক্তকারীকে ছায়া দেবে , তবে এটি কোনও ব্যবহৃত নেমস্পেসের ছায়া দেবে না । এর প্রভাবটি অদ্ভুত হবে, যে কোনও শ্রেণীর থেকে আলাদা নেমস্পেসে এবং একই নেমস্পেস থেকে ব্যবহৃত নেমস্পেসে অ্যাক্সেস আলাদা হবে:

namespace A {
   void foo() {}
   struct B {
      struct foo {};
      void f() {
         foo();      // value initialize a A::B::foo object (current behavior)
      }
   };
}
struct C {
   using namespace A;
   struct foo {};
   void f() {
      foo();         // call A::foo
   }
};
  1. এই শ্রেণীর সুযোগ পরে ডানদিকে তাকান। এটি বেস ক্লাসের সদস্যদের ছায়া দেওয়ার অদ্ভুত প্রভাব ফেলবে। বর্তমানের অনুসন্ধান শ্রেণি এবং নেমস্পেস স্তর স্তরগুলির সাথে মিলিত হয় না এবং শ্রেণিবিন্যাস সম্পাদন করার সময় এটি এনকোলেসিং নেমস্পেস বিবেচনা করার আগে বেস ক্লাসগুলিতে সমস্ত পথে যায় । আচরণটি আশ্চর্যজনক হবে যে এটি নামস্থানটি ঘেরযুক্ত নাম জায়গার সাথে একই স্তরে বিবেচনা করবে না। আবার, ব্যবহৃত নেমস্পেসের সাথে সংযুক্তকরণের স্থানের উপরে অগ্রাধিকার দেওয়া হবে।

namespace A {
   void foo() {}
}
void bar() {}
struct base {
   void foo();
   void bar();
};
struct test : base {
   using namespace A;
   void f() {
      foo();           // A::foo()
      bar();           // base::bar()
   }
};
  1. সংযুক্তকরণের স্থানের ঠিক আগে অনুসন্ধান করুন। এই পদ্ধতির সাথে সমস্যা আবার এটি যে অনেকের কাছে অবাক হবে। বিবেচনা করুন যে নাম স্থানটি একটি ভিন্ন অনুবাদ ইউনিটে সংজ্ঞায়িত করা হয়েছে, যাতে নিম্নলিখিত কোডটি একবারে একবারে দেখা যায় না:

namespace A {
   void foo( int ) { std::cout << "int"; }
}
void foo( double ) { std::cout << "double"; }
struct test {
   using namespace A;
   void f() {
      foo( 5.0 );          // would print "int" if A is checked *before* the
                           // enclosing namespace
   }
};
  1. সংলগ্ন নামের জায়গার সাথে মার্জ করুন। এটি ঠিক একই প্রভাব ফেলবে যা usingনাম স্থান পর্যায়ে ঘোষণাটি প্রয়োগ করে । এটি এতে কোনও নতুন মান যুক্ত করবে না, তবে অন্যদিকে সংকলক বাস্তবায়নকারীদের জন্য অনুসন্ধানকে জটিল করবে। কোডটি যেখানে অনুসন্ধানের সূত্রপাত করেছে সেখান থেকে নেমস্পেস শনাক্তকারী অনুসন্ধান এখন স্বতন্ত্র। শ্রেণীর ভিতরে যখন, শ্রেনীর স্কোপগুলিতে যদি সনাক্তকারী সনাক্ত না করে তবে এটি নামফলন অনুসন্ধানে ফিরে যাবে, তবে এটি ঠিক একই নাম স্থানটি অনুসন্ধান যা কোনও ফাংশন সংজ্ঞাতে ব্যবহৃত হয়, নতুন রাষ্ট্র বজায় রাখার দরকার নেই। যখন usingঘোষণাটি নেমস্পেস স্তরে পাওয়া যায়, ব্যবহৃত নেমস্পেসের বিষয়বস্তু সকলের জন্য সেই নেমস্পেসে আনা হয় জায়গার সাথে জড়িত অনুসন্ধানের । যদিusing namespace শ্রেণি পর্যায়ে অনুমোদিত ছিল, যেখানে অনুসন্ধানটি ট্রিগার করা হয়েছে তার উপর ভিত্তি করে ঠিক একই নেমস্পেসের নেমস্পেস অনুসন্ধানের জন্য আলাদা আলাদা ফলাফল হতে পারে এবং অতিরিক্ত মূল্য ছাড়াই অনুসন্ধানের বাস্তবায়নকে আরও জটিল করে তুলবে।

যাইহোক, আমার সুপারিশটি হ'ল ঘোষণাটি মোটেই কাজে লাগানো using namespaceনয়। এটি সমস্ত নেমস্পেসের বিষয়বস্তু মাথায় না রেখেই যুক্তিযুক্ত কোডটিকে সহজ করে তোলে।


4
আমি সম্মত হই যে ব্যবহারগুলি অন্তর্নিহিত বৈকল্পিকতা তৈরির প্রবণতা ব্যবহার করে। তবে কিছু গ্রন্থাগার usingবিদ্যমান রয়েছে তার আশেপাশে নকশা করা যেতে পারে । গভীর নেস্টেড দীর্ঘস্থানে জায়গাগুলি উদ্দেশ্যমূলকভাবে ঘোষণা করে। যেমন glmতা করে এবং ক্লায়েন্ট যখন ব্যবহার করে তখন বৈশিষ্ট্যগুলি সক্রিয় / উপস্থাপন করতে একাধিক কৌশল ব্যবহার করে using
v.oddou

এমনকি ঠিক এসটিএলে using namespace std::placeholders। cf en.cppreferences.com/w/cpp/utility/functional/bind
v.oddou

@ ভি.ডডু:namespace ph = std::placeholders;
ডেভিড রদ্রিগেজ - ড্রিবিস

1

এটি সম্ভবত উন্মুক্ততা বনাম বন্ধনের কারণে অনুমোদিত নয়

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

ক্লাসে নেমস্পেসগুলি আমদানি করা মজার ক্ষেত্রে এরকম হতে পারে:

namespace Foo {}

struct Bar { using namespace Foo; };

namespace Foo {
using Baz = int; // I've just extended `Bar` with a type alias!
void baz(); // I've just extended `Bar` with what looks like a static function!
// etc.
}

অথবা আমরা কেবল আমদানি করা নাম সহ শ্রেণীর সদস্যদের সংজ্ঞা দিতে পারি না। এই namespace Fooকাঠামোটির সংজ্ঞাটির ভিতরে থাকা সমস্ত কোডের জন্য অনুসন্ধানের অর্ডারে যুক্ত হওয়া যাক struct Bar, যেমন প্রতিটি লাইনটি প্রতিটি ইনলাইন সদস্য ফাংশন বডিতে রাখার মতো, তবে এটি ব্রেস-বা-সমান আরম্ভকারীদের জন্যও সক্রিয় থাকবে ইত্যাদি ইত্যাদি তবে এটি এখনও থাকবে ক্লোজিং ব্রেসে মেয়াদ শেষ হবে, using namespaceসদস্য ফাংশন বডির ভিতরে একই । এখন দুর্ভাগ্যক্রমে এনকোলেসিং নেমস্পেসকে দূষিত না করে কোনও ব্রেস-বা সমমান ইনিশিয়ালাইজারে কোয়েনিগ-সহ-ফ্যালব্যাক লুকের ব্যবহার করার কোনও উপায় বলে মনে হচ্ছে না।
বেন ভয়েগট

0

আমি মনে করি এটি ভাষার একটি ত্রুটি। আপনি নীচে workaround ব্যবহার করতে পারেন। এই কর্মসূচির কথা মাথায় রেখে, ভাষা পরিবর্তন করা হবে তখন মামলার বিরোধের সমাধানের নিয়মের পরামর্শ দেওয়া সহজ।

namespace Hello
{
    typedef int World;
}
// surround the class (where we want to use namespace Hello)
// by auxiliary namespace (but don't use anonymous namespaces in h-files)
namespace Blah_namesp {
using namespace Hello;

class Blah
{
public:
    World DoSomething1();
    World DoSomething2();
    World DoSomething3();
};

World Blah::DoSomething1()
{
}

} // namespace Blah_namesp

// "extract" class from auxiliary namespace
using Blah_namesp::Blah;

Hello::World Blah::DoSomething2()
{
}
auto Blah::DoSomething3() -> World
{
}

আপনি কিছু ব্যাখ্যা যোগ করতে পারেন?
কিশান ভরদা

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