আমি কেন সি ++ এর মধ্যে কোনও ফাংশনের মধ্যে কাঠামো এবং ক্লাসগুলি সংজ্ঞায়িত করতে পারি?


90

আমি ভুলভাবে সি ++ তে এরকম কিছু করেছি এবং এটি কার্যকর হয় works আমি কেন এটি করতে পারি?

int main(int argc, char** argv) {
    struct MyStruct
    {
      int somevalue;
    };

    MyStruct s;
    s.somevalue = 5;
}

এখন এটি করার পরে, আমি এই কৌশলটি কোথাও কোথাও কোথাও পড়ার কথা মনে করি, সি ++ এর জন্য এক ধরণের দরিদ্র-মানুষের ক্রিয়ামূলক প্রোগ্রামিংয়ের সরঞ্জাম হিসাবে, তবে কেন এটি বৈধ, বা আমি কোথায় পড়েছি তা মনে করতে পারছি না।

উভয় প্রশ্নের উত্তর স্বাগত!

দ্রষ্টব্য: যদিও প্রশ্নটি লেখার সময় আমি এই প্রশ্নের কোনও রেফারেন্স পাইনি , বর্তমান সাইড-বারটি এটি নির্দেশ করে তাই আমি এটি এখানে রেফারেন্সের জন্য রেখে দেব, যেভাবেই প্রশ্নটি আলাদা তবে কার্যকর হতে পারে।


উত্তর:


70

[সম্পাদনা 18/4/2013]: সুখের বিষয়, সি ++ 11 এ নীচে উল্লিখিত নিষেধাজ্ঞা প্রত্যাহার করা হয়েছে, সুতরাং স্থানীয়ভাবে সংজ্ঞায়িত ক্লাসগুলি সর্বোপরি দরকারী! কমেন্টার বামবুনকে ধন্যবাদ।

স্থানীয়ভাবে ক্লাস সংজ্ঞায়িত করার ক্ষমতা কাস্টম ফান্টেক্টর তৈরি করবে (একটি সহ ক্লাস operator()(), উদাহরণস্বরূপ পাস করার জন্য তুলনা ফাংশন std::sort()বা "লুপ বডিগুলি" ব্যবহার করার জন্য std::for_each()) আরও অনেক সুবিধাজনক।

দুর্ভাগ্যক্রমে, সি ++ টেমপ্লেট সহ স্থানীয়ভাবে সংজ্ঞায়িত ক্লাস ব্যবহার নিষিদ্ধ করেছে , কারণ তাদের কোনও সংযোগ নেই। যেহেতু ফান্টারের বেশিরভাগ অ্যাপ্লিকেশনগুলি ফ্যামেক্টর প্রকারের সাথে টেম্পলেটযুক্ত সংযুক্ত থাকে, তাই স্থানীয়ভাবে সংজ্ঞায়িত ক্লাসগুলি এর জন্য ব্যবহার করা যায় না - আপনাকে অবশ্যই এগুলি ফাংশনের বাইরে সংজ্ঞায়িত করতে হবে। :(

[সম্পাদনা 1/11/2009]

মান থেকে প্রাসঙ্গিক উক্তিটি হ'ল:

১৪.৩.১ / ২:। একটি স্থানীয় প্রকার, কোনও সংযোগবিহীন প্রকার, একটি নামবিহীন প্রকার বা এই ধরণের যে কোনও থেকে সংক্রামিত কোনও প্রকার টেমপ্লেট-টাইপ-প্যারামিটারের জন্য একটি টেমপ্লেট-যুক্তি হিসাবে ব্যবহৃত হবে না।


4
যদিও অনুগতভাবে, এটি এমএসভিসি ++ 8 এর সাথে কাজ করে বলে মনে হচ্ছে। (তবে জি ++ সহ নয়))
j_random_hacker

আমি জিসিসি ৪.৩.৩ ব্যবহার করছি এবং এটি সেখানে কাজ করছে বলে মনে হচ্ছে: পেস্টবিন . com / f65b876b । মানক যেখানে এটি নিষেধ করে সেখানে আপনার কি কোনও উল্লেখ রয়েছে? আমার কাছে মনে হয় এটি ব্যবহারের সময় সহজেই ইনস্ট্যান্ট করা যেতে পারে।
ক্যাটসকুল

@ ক্যাটসকুল: ১৪.৩.১ / ২: "একটি স্থানীয় প্রকার, কোনও প্রকারের সংযোগবিহীন একটি প্রকার, নামবিহীন প্রকার বা এই ধরণের যে কোনও থেকে মিশ্রিত একটি প্রকার টেমপ্লেট-টাইপ-প্যারামিটারের জন্য একটি টেমপ্লেট-যুক্তি হিসাবে ব্যবহৃত হবে না"। আমার ধারণা, যুক্তিটি হ'ল স্থানীয় ক্লাসগুলিতে মাংলড নামগুলিতে নামানোর জন্য আরও একটি গুচ্ছ তথ্য প্রয়োজন, তবে আমি নিশ্চিত তা জানি না। অবশ্যই কোনও নির্দিষ্ট সংকলক এটি ঘটার জন্য এক্সটেনশনের প্রস্তাব দিতে পারে, যেমনটি এমএসভিসি ++ 8 এবং জি ++ এর সাম্প্রতিক সংস্করণগুলি মনে হয়।
j_random_hacker

9
এই বিধিনিষেধটি সি ++ 11 এ তুলে দেওয়া হয়েছিল।
স্টিফান ডলবার্গ

31

স্থানীয়ভাবে সংজ্ঞায়িত সি ++ ক্লাসগুলির একটি প্রয়োগ কারখানার নকশা প্যাটার্নে রয়েছে :


// In some header
class Base
{
public:
    virtual ~Base() {}
    virtual void DoStuff() = 0;
};

Base* CreateBase( const Param& );

// in some .cpp file
Base* CreateBase( const Params& p )
{
    struct Impl: Base
    {
        virtual void DoStuff() { ... }
    };

    ...
    return new Impl;
}

যদিও আপনি বেনামে নামস্থান দিয়ে একই কাজ করতে পারেন।


মজাদার! যদিও আমি উল্লিখিত টেমপ্লেটগুলি সংক্রান্ত বিধিনিষেধগুলি প্রযোজ্য হবে, এই পদ্ধতির গ্যারান্টি দেয় যে ইমপ্লের দৃষ্টান্তগুলি ক্রিয়েটবেস () ব্যতীত তৈরি করা যায় না (বা এমনকি কথা বলা হয় না!)। সুতরাং এটি ক্লায়েন্টগুলি প্রয়োগের বিশদগুলির উপর নির্ভর করে যে পরিমাণটি হ্রাস করে তা হ্রাস করার একটি দুর্দান্ত উপায় বলে মনে হচ্ছে। +1
j_random_hacker

26
এটি একটি ঝরঝরে ধারণা, আমি শিগগিরই এটি যে কোনও সময় ব্যবহার করব কিনা তা নিশ্চিত নয়, তবে কিছু ছানা ছাপানোর জন্য বারে টানতে খুব সম্ভবত একটি ভাল :)
রবার্ট গোল্ড

4
(আমি বাচ্চাদের
বিটিডাব্লু

9
লল রবার্ট ... হ্যাঁ, সি ++ এর অস্পষ্ট কোণগুলি সম্পর্কে জানার মতো কোনও কিছুই কোনও মহিলাকে খুব বেশি প্রভাবিত করে না ...
j_random_hacker

10

এটি কিছু স্ট্যাক-ভিত্তিক ব্যতিক্রম-সুরক্ষা কাজ করার জন্য খুব দরকারী। বা একাধিক রিটার্ন পয়েন্ট সহ কোনও ফাংশন থেকে সাধারণ পরিষ্কারতা up একে প্রায়শই RAII বলা হয় (সম্পদ অধিগ্রহণের সূচনা হয়)।

void function()
{

    struct Cleaner
    {
        Cleaner()
        {
            // do some initialization code in here
            // maybe start some transaction, or acquire a mutex or something
        }

        ~Cleaner()
        {
             // do the associated cleanup
             // (commit your transaction, release your mutex, etc.)
        }
    };

    Cleaner cleaner;

    // Now do something really dangerous
    // But you know that even in the case of an uncaught exception, 
    // ~Cleaner will be called.

    // Or alternatively, write some ill-advised code with multiple return points here.
    // No matter where you return from the function ~Cleaner will be called.
}

4
Cleaner cleaner();আমি মনে করি এটি কোনও বস্তুর সংজ্ঞা নয় বরং ফাংশন ঘোষণা হবে decla
ব্যবহারকারী

4
@ ব্যবহারকারী আপনি সঠিক। ডিফল্ট কনস্ট্রাক্টরকে কল করতে তার লেখা উচিত Cleaner cleaner;বা Cleaner cleaner{};
কলাইলেটার

ফাংশনের অভ্যন্তরের শ্রেণীর আরএআইআইয়ের সাথে কোনও সম্পর্ক নেই এবং তদ্ব্যতীত, এটি একটি বৈধ সি ++ কোড নয় এবং সংকলন করবে না।
মিখাইল ভাসিলিভ

4
এমনকি ফাংশন ভিতরে, ভালো ক্লাস আছে অবিকল কি সি RAII ++, সব সম্পর্কে।
ক্রিস্টোফার ব্রুনস

9

ভাল, মূলত, কেন না? এ structইন সি (সময়ের ভোরে ফিরে যাওয়া) একটি রেকর্ড কাঠামো ঘোষণার এক উপায় ছিল। আপনি যদি একটি চান, তবে আপনি কেন এটির ঘোষণা করতে সক্ষম হবেন না যেখানে আপনি একটি সাধারণ পরিবর্তনশীল ঘোষণা করবেন?

একবার আপনি এটি করেন, তবে মনে রাখবেন যে সি ++ এর একটি লক্ষ্য যদি সম্ভব হয় তবে সি এর সাথে সামঞ্জস্যপূর্ণ ছিল। তাই থাকল।


বেঁচে থাকার জন্য এক ধরণের ঝরঝরে বৈশিষ্ট্য, তবে জ_আরন্ডম_হ্যাকার কেবল উল্লেখ করেছেন যে আমি সি ++: / /
রবার্ট গোল্ড

হ্যাঁ, স্কোপিংয়ের নিয়মগুলিও সি তে খুব অদ্ভুত ছিল। আমার মনে হয়, এখন আমি সি ++ এর সাথে 25+ বছরের অভিজ্ঞতা পেয়েছি যা সম্ভবত সি এর মতো হওয়ার চেষ্টা করে যাচ্ছিল তারা ভুল হতে পারে। অন্যদিকে, আইফেলের মতো আরও মার্জিত ভাষাগুলি প্রায় ততটা সহজভাবে গ্রহণ করা হয়নি।
চার্লি মার্টিন

হ্যাঁ, আমি একটি বিদ্যমান সি কোডবেস সি ++ এ স্থানান্তরিত করেছি (তবে আইফেলে নয়)।
ChrisW

5

এটিতে উদাহরণ হিসাবে বলা হয়েছে, উদাহরণস্বরূপ, বিভাগ "8.৮: স্থানীয় ক্লাস: ক্লাসের অভ্যন্তর শ্রেণি" http://www.icce.rug.nl/documents/cplusplus/cplusplus07.html যা এটিকে "স্থানীয় শ্রেণি" হিসাবে অভিহিত করে এবং বলে " উত্তরাধিকার বা টেমপ্লেট জড়িত উন্নত অ্যাপ্লিকেশনগুলিতে খুব দরকারী হতে পারে "।


3

এটি সঠিকভাবে শুরু করা বস্তুর অ্যারে তৈরির জন্য।

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

#include <iostream>
using namespace std;

class C {
public:
  C(int x) : mData(x)  {}
  int method() { return mData; }
  // ...
private:
  int mData;
};

void f() {

  // Here I am in f.  I need an array of 50 C objects starting with C(22)

  class D : public C {
  public:
    D() : C(D::clicker()) {}
  private:
    // I want my C objects to be initialized with consecutive
    // integers, starting at 22.
    static int clicker() { 
      static int current = 22;
      return current++;
    } 
  };

  D array[50] ;

  // Now I will display the object in position 11 to verify it got initialized
  // with the right value.  

  cout << "This should be 33: --> " << array[11].method() << endl;

  cout << "sizodf(C): " << sizeof(C) << endl;
  cout << "sizeof(D): " << sizeof(D) << endl;

  return;

}

int main(int, char **) {
  f();
  return 0;
}

সরলতার স্বার্থে, এই উদাহরণটি একটি তুচ্ছ নন-ডিফল্ট নির্মাতা এবং এমন একটি ক্ষেত্রে ব্যবহার করে যেখানে মানগুলি সংকলনের সময় জানা যায়। এই কৌশলটি এমন ক্ষেত্রে প্রসারিত করা সহজ যেখানে আপনি কেবলমাত্র রানটাইমতে জ্ঞাত মানগুলির সাথে আরম্ভ করা অবজেক্টের অ্যারে চান।


অবশ্যই একটি আকর্ষণীয় আবেদন! এটি বুদ্ধিমান বা এমনকি নিরাপদ যদিও নিশ্চিত নয় - আপনার যদি ডিটির এই অ্যারে সি এর অ্যারে হিসাবে বিবেচনা করতে হয় (যেমন আপনাকে এটি একটি D*পরামিতি গ্রহণ করে একটি ক্রিয়াতে প্রেরণ করা দরকার ) তবে চুপচাপ ভেঙে যাবে যদি ডি আসলে সি এর চেয়ে বড় হয় । (আমার মনে হয় ...)
j_random_hacker

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