আমি কেন ব্যক্তিগত প্রকারে অটো ব্যবহার করতে পারি?


139

আমি কোনওভাবে অবাক হয়েছি যে নীচের কোডগুলি সংকলন করে এবং রান করে (vc2012 & gcc4.7.2)

class Foo {
    struct Bar { int i; };
public:
    Bar Baz() { return Bar(); }
};

int main() {
    Foo f;
    // Foo::Bar b = f.Baz();  // error
    auto b = f.Baz();         // ok
    std::cout << b.i;
}

এই কোডটি জরিমানা সংকলন করে কি সঠিক? এবং কেন এটি সঠিক? আমি কেন autoব্যক্তিগত প্রকারে ব্যবহার করতে পারি , যদিও আমি এর নামটি (প্রত্যাশার মতো) ব্যবহার করতে পারি না?


11
এটি f.Baz().iযেমন ঠিক আছে তেমন পর্যবেক্ষণ করুন std::cout << typeid(f.Baz()).name()। শ্রেণীর বাইরের কোডটি "দেখতে" পারে এমন ধরণের ধরণটি Baz()যদি আপনি এটি ধরে রাখতে পারেন তবে আপনি এটির নাম রাখতে পারবেন না।
স্টিভ জেসোপ

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

2
আমি মনে করি যে জিনিসটি মনে রাখবেন তা হ'ল এটি privateএমন যে কোনওভাবে সংকলক প্রয়োগ করতে সহায়তা করতে পারে এমনভাবে API গুলি বর্ণনা করার সুবিধার্থে রয়েছে। এটি Barব্যবহারকারীর দ্বারা প্রকারের অ্যাক্সেস প্রতিরোধ করার উদ্দেশ্যে নয় Foo, সুতরাং এটির Fooউদাহরণ দিয়ে ফিরে সেই অ্যাক্সেসটি সরবরাহ করতে কোনওভাবেই বাধা দেয় না Bar
স্টিভ জেসোপ

1
"এই কোডটি জরিমানা সংকলন করে কি সঠিক?" না। আপনার দরকার #include <iostream>। ;-)
এলএফ

উত্তর:


113

নিয়মগুলি হ'ল autoবেশিরভাগ অংশে, টেম্পলেট টাইপ ছাড়ের মতো। পোস্ট করা উদাহরণটি একই কারণে কাজ করে আপনি ব্যক্তিগত ধরণের অবজেক্টগুলি টেমপ্লেট ফাংশনে পাস করতে পারেন:

template <typename T>
void fun(T t) {}

int main() {
    Foo f;
    fun(f.Baz());         // ok
}

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


32
এবং নামের গোপনীয়তার কোনও প্রকারের সাথে কোনও সম্পর্ক নেই তা দেখতে , প্রশ্নে public: typedef Bar return_type_from_Baz;ক্লাসে যুক্ত করুন Foo। শ্রেণীর একটি ব্যক্তিগত বিভাগে সংজ্ঞায়িত হওয়া সত্ত্বেও, টাইপটি সর্বজনীন নামের দ্বারা সনাক্ত করা যায়।
স্টিভ জেসোপ

1
@ স্টিভের বিন্দু পুনরাবৃত্তি করতে: জন্য অ্যাক্সেসের সুনির্দিষ্টভাবে উল্লেখ করা নাম এটা সঙ্গে কিছুই করার আছে টাইপ হিসাবে জুড়ে দেখা যায়, private: typedef Bar return_type_from_Baz;করতে Fooহিসাবে, প্রদর্শিতtypedef'সনাক্তকারীরা সরকারী এবং বেসরকারী নির্দিষ্টকরণের অ্যাক্সেস সম্পর্কে অসচেতন।
দামিনেহ

এটি আমার কাছে কোনও ধারণা রাখে না। নাম টাইপ নিছক প্রকৃত টাইপ জন্য উপনাম হয়। আমি যদি ফোন করি Barবা তাতে কী আসে যায় SomeDeducedType? এটির মতো নয় যে আমি ব্যক্তিগত class Fooকোনও সদস্য বা কোনও কিছুর কাছে যেতে এটি ব্যবহার করতে পারি।
einpoklum

107

অ্যাক্সেস নিয়ন্ত্রণ নামের প্রয়োগ করা হয় । আদর্শ থেকে এই উদাহরণের সাথে তুলনা করুন:

class A {
  class B { };
public:
  typedef B BB;
};

void f() {
  A::BB x; // OK, typedef name A::BB is public
  A::B y; // access error, A::B is private
}

12

এই প্রশ্নের ইতিমধ্যে চিল এবং আর মার্টিনহো ফার্নান্দেস উভয়ই খুব ভাল উত্তর দিয়েছেন।

আমি হ্যারি পটারের উপমা দিয়ে কোনও প্রশ্নের উত্তর দেওয়ার সুযোগটি পার করতে পারি না:

class Wizard
{
private:
    class LordVoldemort
    {
        void avada_kedavra()
        {
            // scary stuff
        }
    };
public:
    using HeWhoMustNotBeNamed = LordVoldemort;

    friend class Harry;
};

class Harry : Wizard
{
public:
    Wizard::LordVoldemort;
};

int main()
{
    Wizard::HeWhoMustNotBeNamed tom; // OK
    // Wizard::LordVoldemort not_allowed; // Not OK
    Harry::LordVoldemort im_not_scared; // OK
    return 0;
}

https://ideone.com/I5q7gw

হ্যারি ফাঁকটির কথা মনে করিয়ে দেওয়ার জন্য কুইন্টিনকে ধন্যবাদ জানাই।


5
একটি নয় friend class Harry;সেখানে অনুপস্থিত?
কোয়ান্টিন

@ কুইন্টিন আপনি একেবারে সঠিক! সম্পূর্ণতার জন্য একটি সম্ভবত যুক্ত করা উচিত friend class Dumbledore;;)
jpihl

হ্যারি দেখায় না যে তিনি Wizard::LordVoldemort;আধুনিক সি ++ এ ফোন করে ভয় পান না । পরিবর্তে, তিনি কল using Wizard::LordVoldemort;। (ভলডেমর্ট, সততার সাথে ব্যবহার করা এতটা স্বাভাবিক বলে মনে হয় না; ;-)
এলএফ

8

অন্যান্য (ভাল) উত্তর যোগ করার জন্য, এখানে C ++ থেকে 98 একটি উদাহরণ দেখায় যে, যে সমস্যা সত্যিই সঙ্গে কাজ করতে নেই এর autoসব সময়ে

class Foo {
  struct Bar { int i; };
public:
  Bar Baz() { return Bar(); }
  void Qaz(Bar) {}
};

int main() {
  Foo f;
  f.Qaz(f.Baz()); // Ok
  // Foo::Bar x = f.Baz();
  // f.Qaz(x);
  // Error: error: ‘struct Foo::Bar’ is private
}

ব্যক্তিগত প্রকার ব্যবহার নিষিদ্ধ নয়, এটি কেবল প্রকারটির নামকরণ করছিল। এই ধরণের একটি নামবিহীন অস্থায়ী তৈরি করা ঠিক আছে, উদাহরণস্বরূপ, সি ++ এর সমস্ত সংস্করণে।

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