আমি কখন ফরওয়ার্ড ডিক্লেয়ারেশন ব্যবহার করতে পারি?


602

আমি যখন অন্য শ্রেণীর শিরোলেখ ফাইলটিতে কোনও শ্রেণীর অগ্রণী ঘোষণা করার অনুমতি পাই তখন তার সংজ্ঞাটি আমি সন্ধান করছি:

আমি কি বেস ক্লাসের জন্য, সদস্য হিসাবে অনুষ্ঠিত ক্লাসের জন্য, রেফারেন্স ইত্যাদির মাধ্যমে সদস্য ফাংশনে উত্তীর্ণ কোন শ্রেণীর জন্য এটি করার অনুমতি পাচ্ছি?


14
আমি মরিয়া হয়ে চাই যে
এটির

12
@ ডেওয়ার্ড আপনি যখন "কখন" বলবেন আপনি মতামত চাইছেন।
আতুরস্যামস

@ ডেডওয়ারি এটা আমার বোঝার যে আপনি যখনই পারেন সামনের ঘোষণাগুলি ব্যবহার করতে চান, সময় গঠনের উন্নতি করতে এবং বিজ্ঞপ্তি সংক্রান্ত রেফারেন্সগুলি এড়ানোর জন্য। কেবলমাত্র ব্যতিক্রমটি আমি ভাবতে পারি যখন কোনও অন্তর্ভুক্ত ফাইলটিতে টাইপিডেফ থাকে, সেই ক্ষেত্রে টাইপিডেফকে পুনরায় সংজ্ঞায়িত করার (এবং এটি পরিবর্তনের ঝুঁকিপূর্ণ) এবং একটি সম্পূর্ণ ফাইল (তার পুনরাবৃত্তির সাথে অন্তর্ভুক্ত) অন্তর্ভুক্ত করার মধ্যে একটি বাণিজ্য রয়েছে।
ওহাদ স্নাইডার

@ ওহাদস্কিনিডার একটি ব্যবহারিক দৃষ্টিকোণ থেকে, আমি শিরোনামের একটি বড় অনুরাগী নই যে আমার। ÷
ডিফোরে

মূলত সর্বদা তাদের ব্যবহারের জন্য আপনাকে আলাদা শিরোনাম অন্তর্ভুক্ত করতে হবে (কনস্ট্রাক্টর প্যারামিটারের ফরোয়ার্ড
ডেক্সটি

উত্তর:


962

নিজেকে সংকলকের অবস্থানে রাখুন: আপনি যখন কোনও প্রকার ঘোষণা করেন, সমস্ত সংকলক জানেন যে এই ধরণের উপস্থিত রয়েছে; এটি এর আকার, সদস্য বা পদ্ধতি সম্পর্কে কিছুই জানে না। এ কারণেই একে অসম্পূর্ণ প্রকার বলা হয় । সুতরাং, আপনি সদস্যটি বা বেস ক্লাসটি ঘোষণার জন্য টাইপটি ব্যবহার করতে পারবেন না, যেহেতু সংকলকটির ধরণের বিন্যাসটি জানা দরকার।

নিম্নলিখিত সামনের ঘোষণাটি ধরে নেওয়া।

class X;

আপনি যা করতে পারেন এবং কী করতে পারবেন না তা এখানে।

অসম্পূর্ণ প্রকারের মাধ্যমে আপনি কী করতে পারেন:

  • কোনও সদস্যকে পয়েন্টার বা অসম্পূর্ণ প্রকারের রেফারেন্স হিসাবে ঘোষণা করুন:

    class Foo {
        X *p;
        X &r;
    };
    
  • অসম্পূর্ণ প্রকারগুলি গ্রহণ করে / ফেরত দেয় এমন ফাংশন বা পদ্ধতিগুলি ঘোষণা করুন :

    void f1(X);
    X    f2();
    
  • অসম্পূর্ণ প্রকারের (তবে এর সদস্যদের ব্যবহার না করে) পয়েন্টার / রেফারেন্স গ্রহণ / ফিরিয়ে দেওয়ার জন্য এমন কার্য বা পদ্ধতিগুলি সংজ্ঞায়িত করুন :

    void f3(X*, X&) {}
    X&   f4()       {}
    X*   f5()       {}
    

অসম্পূর্ণ প্রকারের সাথে আপনি কী করতে পারবেন না:

  • এটি বেস শ্রেণি হিসাবে ব্যবহার করুন

    class Foo : X {} // compiler error!
  • সদস্য ঘোষণা করার জন্য এটি ব্যবহার করুন:

    class Foo {
        X m; // compiler error!
    };
    
  • এই ধরণের ব্যবহার করে ফাংশন বা পদ্ধতিগুলি সংজ্ঞায়িত করুন

    void f1(X x) {} // compiler error!
    X    f2()    {} // compiler error!
    
  • এর পদ্ধতি বা ক্ষেত্রগুলি ব্যবহার করুন, প্রকৃতপক্ষে অসম্পূর্ণ প্রকারের সাথে একটি ভেরিয়েবলকে অবজ্ঞার চেষ্টা করছেন

    class Foo {
        X *m;            
        void method()            
        {
            m->someMethod();      // compiler error!
            int i = m->someField; // compiler error!
        }
    };
    

এটি যখন টেম্পলেটগুলির ক্ষেত্রে আসে তখন এর কোনও নিখুঁত নিয়ম থাকে না: আপনি কোনও টেম্পলেট প্যারামিটার হিসাবে অসম্পূর্ণ প্রকারটি ব্যবহার করতে পারেন কিনা তা এই ধরণের টেমপ্লেটে কীভাবে ব্যবহৃত হয় তার উপর নির্ভরশীল।

উদাহরণস্বরূপ, std::vector<T>এর প্যারামিটারটি একটি সম্পূর্ণ ধরণের হওয়া boost::container::vector<T>দরকার , যদিও না। কখনও কখনও, আপনি যদি নির্দিষ্ট সদস্য ফাংশন ব্যবহার করেন তবে একটি সম্পূর্ণ ধরণের প্রয়োজন; উদাহরণস্বরূপ, এটি ক্ষেত্রেstd::unique_ptr<T>

একটি ভাল-ডকুমেন্টেড টেম্পলেটটি তার ডকুমেন্টেশনে তার পরামিতিগুলির সমস্ত প্রয়োজনীয়তাগুলি নির্দেশ করতে হবে, যাতে তাদের সম্পূর্ণ ধরণের হওয়া দরকার কি না including


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

2
@ অ্যানডিডেন্ট: সত্য, তবে শিরোনামের গ্রাহককে কেবল তিনি যে নির্ভরতা (গুলি) ব্যবহার করেন সেগুলি অন্তর্ভুক্ত করা দরকার, সুতরাং এটি "আপনি কেবলমাত্র তারাই প্রদান করেন" এর সি ++ নীতি অনুসরণ করে। তবে প্রকৃতপক্ষে, এটি ব্যবহারকারীর পক্ষে অসুবিধাগ্রস্থ হতে পারে যারা শিরোনামটি একক হিসাবে প্রত্যাশা করবে।
লুক টরাইল

8
নিয়মের এই সেটটি একটি অত্যন্ত গুরুত্বপূর্ণ ক্ষেত্রে উপেক্ষা করে: মানক গ্রন্থাগারের বেশিরভাগ টেমপ্লেটগুলি ইনস্ট্যান্ট করার জন্য আপনার একটি সম্পূর্ণ ধরণের দরকার। এটিতে বিশেষভাবে নজর দেওয়া দরকার, কারণ নিয়ম লঙ্ঘন করলে অপরিজ্ঞাত আচরণের ফলাফল হয় এবং সংকলক ত্রুটির কারণ নাও হতে পারে।
জেমস কানজে

12
"নিজেকে সংকলকের অবস্থানে রাখুন" এর জন্য +1। আমি গোঁফ থাকার "সংকলক হচ্ছে" কল্পনা করি।
পাস্কালভিকিউটেন

3
@ জেসুস ক্রিসট: হুবহু: আপনি যখন কোনও বস্তুর দ্বারা মূল্য পাস করেন, সংকলকটিকে যথাযথ স্ট্যাকের হেরফের করার জন্য তার আকারটি জানতে হবে; পয়েন্টার বা রেফারেন্সটি পাস করার সময়, সংকলকটির জন্য অবজেক্টের আকার বা বিন্যাসের প্রয়োজন হয় না, কেবল কোনও ঠিকানার আকার (অর্থাত্ পয়েন্টারের আকার), যা নির্দেশিত ধরণের উপর নির্ভর করে না।
লুক টুরাইল

45

প্রধান নিয়মটি হ'ল আপনি কেবল সেই ক্লাসগুলি ফরোয়ার্ড-ডিক্লেয়ার করতে পারবেন যার মেমরি লেআউট (এবং এইভাবে সদস্য ফাংশন এবং ডেটা সদস্য) আপনার ফরোয়ার্ড-ডিক্লেয়ার করা ফাইলে জানা দরকার নেই।

এটি বেস ক্লাস এবং রেফারেন্স এবং পয়েন্টারগুলির মাধ্যমে ব্যবহৃত ক্লাস ছাড়া কিছু বাদ দেয়।


6
প্রায়। ফাংশন প্রোটোটাইপগুলিতে প্যারামিটার বা রিটার্ন টাইপের হিসাবে আপনি "প্লেইন" (অর্থাত্ নন-পয়েন্টার / রেফারেন্স) অসম্পূর্ণ প্রকারগুলিও উল্লেখ করতে পারেন।
j_random_hacker

আমি শিরোনাম ফাইলটিতে সংজ্ঞায়িত ক্লাসের সদস্য হিসাবে যে ক্লাসগুলি ব্যবহার করতে চাই সেগুলি সম্পর্কে কী? আমি কি তাদের ঘোষণা করতে পারি?
ইগোর ওকস

1
হ্যাঁ, তবে সেক্ষেত্রে আপনি কেবলমাত্র ফরওয়ার্ড ঘোষিত শ্রেণীর জন্য একটি রেফারেন্স বা পয়েন্টার ব্যবহার করতে পারেন। তবে তা সত্ত্বেও আপনার সদস্য হতে দেয়।
রুনুনেন

32

Lakos শ্রেণীর ব্যবহারের মধ্যে পার্থক্য করে

  1. কেবলমাত্র নামমাত্র (যার জন্য একটি ফরওয়ার্ড ঘোষণা যথেষ্ট) এবং
  2. ইন-সাইজ (যার জন্য বর্গ সংজ্ঞা প্রয়োজন)।

আমি এটি আরও সাফল্যের সাথে উচ্চারণ কখনও দেখিনি :)


2
নামমাত্র মানে কি?
বুড়ো

4
@ বুন: সাহস আমি বলি ...? আপনি যদি কেবল ক্লাসের নাম ব্যবহার করেন ?
মার্ক মুটজ - মিমুতজ

1
প্লাস ওয়ান লাকোসের জন্য, মার্ক
mlvljr

28

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

উদাহরণ:

struct X;              // Forward declaration of X

void f1(X* px) {}      // Legal: can always use a pointer
void f2(X&  x) {}      // Legal: can always use a reference
X f3(int);             // Legal: return value in function prototype
void f4(X);            // Legal: parameter in function prototype
void f5(X) {}          // ILLEGAL: *definitions* require complete types

19

এখন পর্যন্ত যে কোনও উত্তর বর্ণিত নয় যখন যখন কোনও শ্রেণি টেমপ্লেটের একটি অগ্রণী ঘোষণা ব্যবহার করতে পারে। সুতরাং, এখানে এটি যায়।

একটি শ্রেণিবদ্ধ টেমপ্লেট হিসাবে ঘোষণা করা যেতে পারে:

template <typename> struct X;

গৃহীত উত্তরের কাঠামো অনুসরণ করে ,

আপনি যা করতে পারেন এবং কী করতে পারবেন না তা এখানে।

অসম্পূর্ণ প্রকারের মাধ্যমে আপনি কী করতে পারেন:

  • কোনও সদস্যকে পয়েন্টার বা অন্য শ্রেণীর টেম্পলেটের অসম্পূর্ণ প্রকারের রেফারেন্স হিসাবে ঘোষণা করুন:

    template <typename T>
    class Foo {
        X<T>* ptr;
        X<T>& ref;
    };
  • কোনও সদস্যকে পয়েন্টার বা তার অসম্পূর্ণ ইনস্ট্যানটিশনের একটি রেফারেন্স হিসাবে ঘোষণা করুন:

    class Foo {
        X<int>* ptr;
        X<int>& ref;
    };
  • ফাংশন টেম্পলেট বা সদস্য ফাংশন টেম্পলেটগুলি ঘোষণা করুন যা অসম্পূর্ণ প্রকারগুলি গ্রহণ করে / ফেরত দেয়:

    template <typename T>
       void      f1(X<T>);
    template <typename T>
       X<T>    f2();
  • কার্যাবলী বা সদস্য ফাংশনগুলি ঘোষণা করুন যা এর অসম্পূর্ণ ইনস্ট্যানটিশনের একটি গ্রহণ করে / ফেরত দেয়:

    void      f1(X<int>);
    X<int>    f2();
  • ফাংশন টেম্পলেট বা সদস্য ফাংশন টেম্পলেটগুলি সংজ্ঞায়িত করুন যা অসম্পূর্ণ প্রকারের (তবে এর সদস্যদের ব্যবহার না করে) পয়েন্টার / রেফারেন্স গ্রহণ করে / ফেরত দেয়:

    template <typename T>
       void      f3(X<T>*, X<T>&) {}
    template <typename T>
       X<T>&   f4(X<T>& in) { return in; }
    template <typename T>
       X<T>*   f5(X<T>* in) { return in; }
  • ফাংশন বা পদ্ধতিগুলি সংজ্ঞায়িত করে যা এর অসম্পূর্ণ ইনস্ট্যান্টেশনগুলির একটিতে (তবে এর সদস্যদের ব্যবহার না করে) পয়েন্টার / রেফারেন্স গ্রহণ করে / ফেরত দেয়:

    void      f3(X<int>*, X<int>&) {}
    X<int>&   f4(X<int>& in) { return in; }
    X<int>*   f5(X<int>* in) { return in; }
  • এটি অন্য টেম্পলেট শ্রেণীর বেস ক্লাস হিসাবে ব্যবহার করুন

    template <typename T>
    class Foo : X<T> {} // OK as long as X is defined before
                        // Foo is instantiated.
    
    Foo<int> a1; // Compiler error.
    
    template <typename T> struct X {};
    Foo<int> a2; // OK since X is now defined.
  • অন্য শ্রেণীর টেম্পলেটটির সদস্য ঘোষণার জন্য এটি ব্যবহার করুন:

    template <typename T>
    class Foo {
        X<T> m; // OK as long as X is defined before
                // Foo is instantiated. 
    };
    
    Foo<int> a1; // Compiler error.
    
    template <typename T> struct X {};
    Foo<int> a2; // OK since X is now defined.
  • এই ধরণের ব্যবহার করে ফাংশন টেম্পলেট বা পদ্ধতিগুলি সংজ্ঞায়িত করুন

    template <typename T>
      void    f1(X<T> x) {}    // OK if X is defined before calling f1
    template <typename T>
      X<T>    f2(){return X<T>(); }  // OK if X is defined before calling f2
    
    void test1()
    {
       f1(X<int>());  // Compiler error
       f2<int>();     // Compiler error
    }
    
    template <typename T> struct X {};
    
    void test2()
    {
       f1(X<int>());  // OK since X is defined now
       f2<int>();     // OK since X is defined now
    }

অসম্পূর্ণ প্রকারের সাথে আপনি কী করতে পারবেন না:

  • বেস ক্লাস হিসাবে এর একটি ইনস্ট্যান্টেশন ব্যবহার করুন

    class Foo : X<int> {} // compiler error!
  • সদস্য ঘোষণা করার জন্য এর একটি তাত্ক্ষণিক ব্যবহার করুন:

    class Foo {
        X<int> m; // compiler error!
    };
  • এর কোনও একটি ইনস্ট্যান্টেশন ব্যবহার করে ফাংশন বা পদ্ধতিগুলি সংজ্ঞায়িত করুন

    void      f1(X<int> x) {}            // compiler error!
    X<int>    f2() {return X<int>(); }   // compiler error!
  • প্রকৃতপক্ষে অসম্পূর্ণ প্রকারের সাথে একটি ভেরিয়েবলকে অবজ্ঞার চেষ্টা করার জন্য এর কোনও একটি ইনস্ট্যান্টের পদ্ধতি বা ক্ষেত্রগুলি ব্যবহার করুন

    class Foo {
        X<int>* m;            
        void method()            
        {
            m->someMethod();      // compiler error!
            int i = m->someField; // compiler error!
        }
    };
  • শ্রেণীর টেম্পলেটটির সুস্পষ্ট তাত্পর্য তৈরি করুন

    template struct X<int>;

2
"এখন পর্যন্ত উত্তরগুলির মধ্যে কোনওটিই বর্ণনা করে না যে যখন কোনও শ্রেণি টেম্পলেটটির অগ্রিম ঘোষণা করতে পারে।" নয় যে কেবল কারণ শব্দার্থবিদ্যা Xএবং X<int>ঠিক একই, এবং শুধুমাত্র কোন বাস্তব ভাবে এগিয়ে-প্রকাশক সিনট্যাক্স পৃথক, সব কিন্তু লুক এবং গ্রহণ আপনার উত্তর অংকের 1 লাইন s/X/X<int>/g? আসলেই কি দরকার? বা আমি কি আলাদা একটি ছোট বিবরণ মিস করেছি? এটি সম্ভব, তবে আমি দৃশ্যত কয়েকবার তুলনা করেছি এবং কোনও দেখতে পাচ্ছি না ...
আন্ডারস্কোর_১২

ধন্যবাদ! এই সম্পাদনাটি এক টন মূল্যবান তথ্য যুক্ত করে। এটি পুরোপুরি বুঝতে আমার এটি বেশ কয়েকবার পড়তে হবে ... অথবা যতক্ষণ না আমি সত্যিকারের কোডগুলিতে ভয়াবহভাবে বিভ্রান্ত হয়ে এখানে ফিরে আসছি ততক্ষণ অপেক্ষা করার সর্বোত্তম কৌশলটি ব্যবহার করতে পারি! আমার সন্দেহ হয় যে আমি এটি বিভিন্ন জায়গায় নির্ভরতা হ্রাস করতে ব্যবহার করতে সক্ষম হব।
আন্ডারস্কোর_ডি

4

যে ফাইলে আপনি কেবলমাত্র পয়েন্টার বা কোনও শ্রেণীর রেফারেন্স ব্যবহার করেন nd এবং কোনও সদস্য / সদস্য ক্রিয়াকলাপটি সেই পয়েন্টার / রেফারেন্স হিসাবে বিবেচনা করা উচিত নয়।

সঙ্গে class Foo;// এগিয়ে ঘোষণা

আমরা ফু * বা ফু & প্রকারের ডেটা সদস্যদের ঘোষণা করতে পারি।

আমরা Foo টাইপের আর্গুমেন্ট এবং / অথবা রিটার্ন মান সহ ফাংশনগুলি ঘোষণা করতে পারি (তবে সংজ্ঞায়িত করি না) can

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


4

আমি এটিকে একটি মন্তব্য করার পরিবর্তে পৃথক উত্তর হিসাবে লিখছি কারণ লুচ টুরাইলের উত্তরটির সাথে আমি বৈধতার ভিত্তিতে নয়, শক্তিশালী সফ্টওয়্যার এবং ভুল ব্যাখ্যা করার বিপদের জন্য একমত নই।

বিশেষত, আপনার ইন্টারফেসের ব্যবহারকারীদের কী জানতে হবে বলে আপনি আশা করছেন তার অন্তর্নিহিত চুক্তিতে আমার একটি সমস্যা রয়েছে।

আপনি যদি ফিরে আসছেন বা রেফারেন্সের ধরণগুলি স্বীকার করছেন, তবে আপনি কেবল বলছেন যে তারা কোনও পয়েন্টার বা রেফারেন্সের মধ্য দিয়ে যেতে পারে যা তারা কেবলমাত্র একটি অগ্রণী ঘোষণার মাধ্যমে জানতে পারে।

আপনি যখন কোনও অসম্পূর্ণ প্রকারটি ফিরিয়ে দিচ্ছেন X f2();তখন আপনি বলছেন আপনার কলারের কাছে অবশ্যই এক্স এর পূর্ণ ধরণের স্পেসিফিকেশন থাকতে হবে the কল সাইটে এলএইচএস বা অস্থায়ী বস্তু তৈরি করার জন্য তাদের এটির প্রয়োজন need

একইভাবে, আপনি যদি কোনও অসম্পূর্ণ প্রকার গ্রহণ করেন, কলারটিকে অবজেক্টটি তৈরি করতে হবে যা প্যারামিটার। এমনকি যদি কোনও ফাংশন থেকে সেই অবজেক্টটিকে অন্য একটি অসম্পূর্ণ প্রকার হিসাবে ফিরিয়ে দেওয়া হয়, কল সাইটের পুরো ঘোষণার প্রয়োজন হয়। অর্থাৎ,

class X;  // forward for two legal declarations 
X returnsX();
void XAcceptor(X);

XAcepptor( returnsX() );  // X declaration needs to be known here

আমি মনে করি একটি গুরুত্বপূর্ণ নীতি আছে যে একটি শিরোলেখী অন্যান্য শিরোলেখের আবশ্যক নির্ভরতা ছাড়াই এটি ব্যবহারের জন্য পর্যাপ্ত তথ্য সরবরাহ করে। এর অর্থ হ্যান্ডারটি কোনও ঘোষণাপত্র ব্যবহার করে যখন কোনও সংকলক ত্রুটি সৃষ্টি না করে সংকলন ইউনিটে অন্তর্ভুক্ত করতে সক্ষম হওয়া উচিত।

ছাড়া

  1. যদি এই বাহ্যিক নির্ভরতা কাঙ্ক্ষিত আচরণ হয়। শর্তসাপেক্ষ সংকলনটি ব্যবহার করার পরিবর্তে আপনার নিজের নিজস্ব শিরোনাম X ঘোষিত সরবরাহের জন্য তাদের জন্য একটি ডকুমেন্টেড প্রয়োজনীয়তা থাকতে পারে # এটি #ifdefs ব্যবহারের বিকল্প এবং এটি উপহাস বা অন্যান্য রূপগুলি উপস্থাপনের একটি কার্যকর উপায় হতে পারে।

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


"আমি মনে করি একটি গুরুত্বপূর্ণ নীতি আছে যে শিরোনামের অন্যান্য শিরোনামের প্রয়োজন হয় না নির্ভরতা ব্যতীত এটি ব্যবহারের জন্য পর্যাপ্ত তথ্য সরবরাহ করা উচিত" " - নবীনের উত্তর সম্পর্কে অ্যাড্রিয়ান ম্যাকার্থির একটি মন্তব্যে আরেকটি বিষয় উল্লেখ করা হয়েছে। এটি বর্তমানে আপনার অ-তাত্পর্যপূর্ণ প্রকারের জন্য এমনকি আপনার "ব্যবহারের জন্য পর্যাপ্ত তথ্য সরবরাহ করতে হবে" নীতি অনুসরণ না করার একটি উপযুক্ত কারণ সরবরাহ করে।
টনি ডেলরয়

3
যখন বলছ উচিত (অথবা উচিত নয়) এগিয়ে declarion ব্যবহার করুন। যদিও এটি পুরোপুরি এই প্রশ্নের বিন্দু নয়। এটি প্রযুক্তিগত সম্ভাবনাগুলি সম্পর্কে জানার বিষয়ে (যখন উদাহরণস্বরূপ) একটি বিজ্ঞপ্তি নির্ভরতা সমস্যাটি ভাঙতে চায়।
জনি জেডি

1
I disagree with Luc Touraille's answerসুতরাং দৈর্ঘ্যের প্রয়োজন হলে তাকে একটি ব্লগ পোস্টের লিঙ্ক সহ একটি মন্তব্য লিখুন। এটি জিজ্ঞাসিত প্রশ্নের উত্তর দেয় না। এক্স যদি X এর সাথে মতবিরোধ না করে কীভাবে যুক্তিসঙ্গত জবাবগুলি নিয়ে কাজ করে বা আমাদের সীমাবদ্ধতার সাথে এক্স ব্যবহারের আমাদের স্বাধীনতাকে বাধা দেওয়া উচিত সে সম্পর্কে প্রশ্নগুলি যদি সবার মনে হয় - তবে আমাদের প্রায় কোনও বাস্তব উত্তর নেই have
আন্ডারস্কোর_ডি

3

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


2
এটি এনক্যাপসুলেশন বিরতি দেয় এবং কোড ভঙ্গুর করে তোলে। এটি করার জন্য, আপনার ডিফল্ট টেম্পলেট প্যারামিটার সহ টাইপডেফ বা শ্রেণীর টেম্পলেটগুলির জন্য কোনও শ্রেণি কিনা তা জানতে হবে এবং যদি প্রয়োগটি কখনও পরিবর্তিত হয় তবে আপনি কোনও অগ্রণী ঘোষণা ব্যবহার করেছেন এমন জায়গা আপডেট করতে হবে।
অ্যাড্রিয়ান ম্যাকার্থি

@ অ্যাড্রিয়ানম্যাকার্থি সঠিক, এবং একটি যুক্তিসঙ্গত সমাধান হ'ল একটি ফরোয়ার্ড ডিক্লেয়ারেশন শিরোলেখ থাকে যা এতে হেডারের অন্তর্ভুক্ত থাকে যার বিষয়বস্তু এটি ফরোয়ার্ড ঘোষণা করে, যার মালিকানাধীন / বজায় রাখা উচিত / যাকেও এই শিরোলেখের মালিকানাধীন পাঠানো উচিত। উদাহরণস্বরূপ: iosfwd স্ট্যান্ডার্ড লাইব্রেরির শিরোনাম, এতে iostream সামগ্রীর ফরোয়ার্ড ঘোষণা রয়েছে।
টনি ডেলরয়

3

যতক্ষণ আপনার সংজ্ঞাটির প্রয়োজন নেই (পয়েন্টার এবং রেফারেন্সগুলি ভাবেন) আপনি ফরোয়ার্ড ঘোষণা দিয়ে দূরে যেতে পারবেন। এ কারণেই সাধারণত আপনি এগুলি শিরোনামে দেখতে পান যখন বাস্তবায়নকারী ফাইলগুলি যথাযথ সংজ্ঞা (গুলি) এর জন্য শিরোনামকে টান দেয়।


0

আপনি ক্লাসের সদস্য হিসাবে অন্য ধরণের (শ্রেণি) ব্যবহার করতে চাইলে আপনি সাধারণত ক্লাস শিরোনাম ফাইলে ফরওয়ার্ড ডিক্লেয়ারেশন ব্যবহার করতে চান। আপনি হেডার ফাইলে ফরওয়ার্ড-ঘোষিত ক্লাসের পদ্ধতিগুলি ব্যবহার করতে পারবেন না কারণ C ++ সেই পর্বে এখনও সেই শ্রেণীর সংজ্ঞাটি জানে না। এটি যুক্তিযুক্ত যে আপনাকে .cpp-ফাইলগুলিতে স্থানান্তর করতে হবে, তবে আপনি যদি টেমপ্লেট-ফাংশন ব্যবহার করছেন তবে আপনাকে সেগুলি কেবলমাত্র সেই অংশে হ্রাস করা উচিত যা টেমপ্লেটটি ব্যবহার করে এবং সেই ফাংশনটিকে শিরোনামে স্থানান্তরিত করে।


এর কোন মানে নেই. একজনের অসম্পূর্ণ ধরণের সদস্য থাকতে পারে না। যে কোনও শ্রেণীর ঘোষণায় অবশ্যই সমস্ত ব্যবহারকারীকে এর আকার এবং বিন্যাস সম্পর্কে যা জানতে হবে তা সরবরাহ করতে হবে। এর আকারে এর সমস্ত অ-স্থিতিশীল সদস্যের মাপ অন্তর্ভুক্ত রয়েছে। ফরোয়ার্ড-ঘোষণা কোনও সদস্যকে এর আকার সম্পর্কে কোনও ধারণা ছাড়াই ছেড়ে দেয়।
আন্ডারস্কোর_ডে

0

এটি গ্রহণ করুন যে সামনের ঘোষণাপত্রটি আপনার কোডটি সংকলন করতে পাবে (আপত্তি তৈরি হয়েছে)। সংজ্ঞাটি পাওয়া না গেলেও লিঙ্কিং (উদাহরণ সৃষ্টি) সফল হবে না।


2
কেন 2 জন লোক কেন এটিকে অগ্রাহ্য করেছিল? আপনি যে প্রশ্নটি করছেন তা নিয়ে আপনি কথা বলছেন না। আপনার অর্থ স্বাভাবিক - ফরোয়ার্ড নয় - ফাংশনগুলির ঘোষণা । প্রশ্নটি ক্লাসের ফরওয়ার্ড-ডিক্লেয়ারেশন নিয়ে । আপনি যেমন বলেছিলেন যে "ফরওয়ার্ড ডিক্লেয়ারেশনটি আপনার কোডটি সংকলন করতে পাবে", আমাকে দয়া করুন: সংকলন করুন class A; class B { A a; }; int main(){}এবং আমাকে কীভাবে তা জানাতে দিন। অবশ্যই এটি সংকলন করবে না। সকল সঠিক উত্তর এখানে কেন এবং সুনির্দিষ্ট, সীমাবদ্ধ প্রেক্ষিতে যা বিচক্ষণ ঘোষণা ব্যাখ্যা হল বৈধ। আপনি পরিবর্তে একেবারে ভিন্ন কিছু সম্পর্কে এটি লিখেছেন।
আন্ডারস্কোর_১২

0

আমি কেবল একটি গুরুত্বপূর্ণ জিনিস যুক্ত করতে চাই যা আপনি ফরোয়ার্ড শ্রেণীর সাথে করতে পারেন লুচ টুরাইলের উত্তরে উল্লেখ নেই।

অসম্পূর্ণ প্রকারের মাধ্যমে আপনি কী করতে পারেন:

অসম্পূর্ণ প্রকারের পয়েন্টার / রেফারেন্সগুলি গ্রহণ / প্রত্যাবর্তনকারী ফাংশন বা পদ্ধতিগুলি সংজ্ঞায়িত করে এবং অন্য ফাংশনে পয়েন্টার / রেফারেন্স ফরোয়ার্ড করে।

void  f6(X*)       {}
void  f7(X&)       {}
void  f8(X* x_ptr, X& x_ref) { f6(x_ptr); f7(x_ref); }

একটি মডিউল একটি ফরোয়ার্ড ঘোষিত শ্রেণীর একটি বস্তুর মধ্য দিয়ে অন্য মডিউলে যেতে পারে।


"একটি ফরোয়ার্ড ক্লাস" এবং "একটি ফরোয়ার্ড ঘোষিত শ্রেণি" দুটি খুব আলাদা জিনিস উল্লেখ করতে ভুল হতে পারে। আপনি যা লিখেছেন তা লুসের উত্তরে অন্তর্নিহিত ধারণাগুলি থেকে সরাসরি অনুসরণ করা হয়েছে, সুতরাং এটি একটি স্পষ্ট মন্তব্য দিয়ে একটি ভাল মন্তব্য করেছে, তবে আমি নিশ্চিত নই যে এটি কোনও উত্তরকে ন্যায়সঙ্গত করেছে।
আন্ডারস্কোর_ডে

0

যেমন লুস টুরাইল ক্লাসের ফরোয়ার্ড ডিক্লেয়ারেশনটি কোথায় ব্যবহার করবেন এবং ব্যবহার করবেন না তা ইতিমধ্যে এটি খুব ভালভাবে ব্যাখ্যা করেছে।

আমি কেবল এটি যুক্ত করব কেন আমাদের এটি ব্যবহার করা দরকার।

অযাচিত নির্ভরতা ইনজেকশনটি এড়াতে আমাদের যেখানেই সম্ভব ফরোয়ার্ড ডিক্লেয়ারেশন ব্যবহার করা উচিত।

যেহেতু #includeএকাধিক ফাইলগুলিতে শিরোনাম ফাইল যুক্ত করা হয়, আমরা যদি অন্য শিরোলেখ ফাইলটিতে একটি শিরোনাম যুক্ত করি তবে এটি উত্স কোডের বিভিন্ন অংশে অবাঞ্ছিত নির্ভরতা ইনজেকশন যুক্ত করবে যা অন্য হেডার ফাইলগুলিতে যুক্ত করার পরিবর্তে যেখানেই সম্ভব ফাইলগুলিতে #includeহেডার যুক্ত করে এড়ানো যেতে পারে .cppএবং শিরোনাম .hফাইলগুলিতে যেখানে সম্ভব ক্লাস ফরোয়ার্ড ডিক্লেয়ারেশন ব্যবহার করুন ।

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