खोज…


वाक्य - विन्यास

  • // कॉलिंग:

    • variable.member_function ();
    • variable_pointer-> member_function ();
  • // परिभाषा:

    • ret_type class_name :: सदस्य_function () cv-qualifiers {
      • तन;
    • }
  • // प्रोटोटाइप:

    • वर्ग class_name {
      • virt-Specier ret_type सदस्य_function () cv-qualifiers गुण-विशेषक-seq;
      • // गुण-निर्दिष्ट: "आभासी", यदि लागू हो।
      • // cv-क्वालिफायर: "कास्ट" और / या "वाष्पशील", यदि लागू हो।
      • // गुण-विशेष-seq: "ओवरराइड" और / या "अंतिम", यदि लागू हो।
    • }

टिप्पणियों

एक गैर- static सदस्य फ़ंक्शन एक class / struct / union सदस्य फ़ंक्शन है, जिसे किसी विशेष उदाहरण पर कहा जाता है, और कहा उदाहरण पर कार्य करता है। static सदस्य कार्यों के विपरीत, यह एक उदाहरण निर्दिष्ट किए बिना नहीं बुलाया जा सकता है।

कक्षाओं, संरचनाओं और यूनियनों के बारे में जानकारी के लिए, कृपया मूल विषय देखें

गैर-स्थैतिक सदस्य कार्य

एक class या struct में सदस्य कार्यों के साथ-साथ सदस्य चर भी हो सकते हैं। इन फ़ंक्शंस में सिंटैक्स ज्यादातर स्टैंडअलोन फ़ंक्शंस के समान होता है, और इसे क्लास परिभाषा के अंदर या बाहर परिभाषित किया जा सकता है; यदि वर्ग परिभाषा के बाहर परिभाषित किया जाता है, तो फ़ंक्शन का नाम कक्षा के नाम और कार्यक्षेत्र ( :: :) ऑपरेटर के साथ उपसर्ग किया जाता है।

class CL {
  public:
    void  definedInside() {}
    void definedOutside();
};
void CL::definedOutside() {}

इन कार्यों को डॉट ( . ) ऑपरेटर के साथ वर्ग के एक उदाहरण (या उदाहरण के लिए) पर बुलाया जाता है, या तीर ( -> ) ऑपरेटर के साथ एक उदाहरण के लिए एक सूचक, और प्रत्येक कॉल फ़ंक्शन के उदाहरण से जुड़ा होता है पर बुलाया गया था; जब एक सदस्य फ़ंक्शन को एक उदाहरण पर कॉल किया जाता है, तो उस इंस्टेंस के सभी फ़ील्ड ( this पॉइंटर के माध्यम से) तक उसकी पहुंच होती है, लेकिन केवल अन्य इंस्टेंस के फ़ील्ड्स तक ही पहुँच प्राप्त कर सकते हैं यदि उन इंस्ट्रूमेंट्स को पैरामीटर के रूप में आपूर्ति की जाती है।

struct ST {
    ST(const std::string& ss = "Wolf", int ii = 359) : s(ss), i(ii) { }

    int get_i() const { return i; }
    bool compare_i(const ST& other) const { return (i == other.i); }

  private:
    std::string s;
    int i;
};
ST st1;
ST st2("Species", 8472);

int  i = st1.get_i(); // Can access st1.i, but not st2.i.
bool b = st1.compare_i(st2); // Can access st1 & st2.

इन कार्यों को सदस्य चर और / या अन्य सदस्य कार्यों का उपयोग करने की अनुमति दी जाती है, भले ही चर या फ़ंक्शन के एक्सेस संशोधक की परवाह किए बिना। उन्हें आउट-ऑफ-ऑर्डर भी लिखा जा सकता है, सदस्य चर और / या कॉलिंग सदस्य कार्यों को उनके सामने घोषित किया जा सकता है, क्योंकि कंपाइलर एक क्लास को संकलित करने के लिए शुरू करने से पहले पूरी कक्षा की परिभाषा को पार्स किया जाना चाहिए।

class Access {
  public:
    Access(int i_ = 8088, int j_ = 8086, int k_ = 6502) : i(i_), j(j_), k(k_) {}

    int i;
    int get_k() const { return k; }
    bool private_no_more() const { return i_be_private(); }
  protected:
    int j;
    int get_i() const { return i; }
  private:
    int k;
    int get_j() const { return j; }
    bool i_be_private() const { return ((i > j) && (k < j)); }
};

encapsulation

सदस्य कार्यों का उपयोग आम तौर पर कैप्सूलीकरण के लिए है, बजाय सीधे क्षेत्रों तक पहुँचने का एक्सेसर (आमतौर पर एक गेटर रूप में जाना जाता है) और एक mutator (आमतौर पर एक सेटर के रूप में जाना जाता है) का उपयोग कर।

class Encapsulator {
    int encapsulated;

  public:
    int  get_encapsulated() const { return encapsulated; }
    void set_encapsulated(int e)  { encapsulated = e; }

    void some_func() {
        do_something_with(encapsulated);
    }
};

वर्ग के अंदर, encapsulated को किसी भी गैर-स्थैतिक सदस्य फ़ंक्शन द्वारा स्वतंत्र रूप से एक्सेस किया जा सकता है; वर्ग के बाहर, इसका उपयोग सदस्य कार्यों द्वारा विनियमित होता है, इसे पढ़ने के लिए get_encapsulated() का उपयोग करके और इसे संशोधित करने के लिए set_encapsulated() का उपयोग करते हुए। यह चर के लिए अनजाने संशोधनों को रोकता है, क्योंकि इसे पढ़ने और लिखने के लिए अलग-अलग फ़ंक्शन का उपयोग किया जाता है। [दोनों दावों के लिए अच्छे तर्क के साथ गेटर्स और सेटर्स इनकैप्सुलेशन प्रदान करते हैं या तोड़ते हैं या नहीं, इस पर कई चर्चाएं हैं; इस तरह की गरमागरम बहस इस उदाहरण के दायरे से बाहर है।]

नाम छिपाना और आयात करना

जब एक बेस क्लास ओवरलोड कार्यों का एक सेट प्रदान करता है, और एक व्युत्पन्न वर्ग सेट पर एक और अधिभार जोड़ता है, यह बेस क्लास द्वारा प्रदान किए गए सभी ओवरलोड को छुपाता है।

struct HiddenBase {
    void f(int) { std::cout << "int" << std::endl; }
    void f(bool) { std::cout << "bool" << std::endl; }
    void f(std::string) { std::cout << "std::string" << std::endl; }
};

struct HidingDerived : HiddenBase {
    void f(float) { std::cout << "float" << std::endl; }
};

// ...

HiddenBase hb;
HidingDerived hd;
std::string s;

hb.f(1);    // Output:  int
hb.f(true); // Output:  bool
hb.f(s);    // Output:  std::string;

hd.f(1.f);  // Output:  float
hd.f(3);    // Output:  float
hd.f(true); // Output:  float
hd.f(s);    // Error: Can't convert from std::string to float.

यह नाम रिज़ॉल्यूशन नियमों के कारण है: नाम देखने के दौरान, एक बार सही नाम मिल जाने के बाद, हम hd.f(s) बंद कर देते हैं, भले ही हमें स्पष्ट रूप से उस नाम के साथ इकाई का सही संस्करण नहीं मिला हो (जैसे कि hd.f(s) ); इसके कारण, व्युत्पन्न वर्ग में फ़ंक्शन को ओवरलोड करना बेस क्लास में ओवरलोड को खोजने से नाम देखने को रोकता है। इससे बचने के लिए, बेस क्लास से नामों को व्युत्पन्न वर्ग में "इम्पोर्ट" करने के लिए एक यूज़-डिक्लेरेशन का उपयोग किया जा सकता है, ताकि वे नाम देखने के दौरान उपलब्ध रहें।

struct HidingDerived : HiddenBase {
     // All members named HiddenBase::f shall be considered members of HidingDerived for lookup.
    using HiddenBase::f;

    void f(float) { std::cout << "float" << std::endl; }
};

// ...

HidingDerived hd;

hd.f(1.f);  // Output:  float
hd.f(3);    // Output:  int
hd.f(true); // Output:  bool
hd.f(s);    // Output:  std::string

यदि एक व्युत्पन्न वर्ग एक प्रयोग-घोषणा के साथ नाम आयात करता है, लेकिन बेस क्लास में फ़ंक्शन के रूप में समान हस्ताक्षर के साथ फ़ंक्शन भी घोषित करता है, तो बेस क्लास फ़ंक्शन चुपचाप ओवरराइड या छिप जाएंगे।

struct NamesHidden {
    virtual void hide_me()      {}
    virtual void hide_me(float) {}
    void hide_me(int)           {}
    void hide_me(bool)          {}
};

struct NameHider : NamesHidden {
    using NamesHidden::hide_me;

    void hide_me()    {} // Overrides NamesHidden::hide_me().
    void hide_me(int) {} // Hides NamesHidden::hide_me(int).
};

एक्सेस-मॉडिफ़ायर को बदलने के लिए एक उपयोग-घोषणा का भी उपयोग किया जा सकता है, बशर्ते आयातित इकाई public या बेस क्लास में protected थी।

struct ProMem {
  protected:
    void func() {}
};

struct BecomesPub : ProMem {
    using ProMem::func;
};

// ...

ProMem pm;
BecomesPub bp;

pm.func(); // Error: protected.
bp.func(); // Good.

इसी तरह, यदि हम स्पष्ट रूप से वंशानुक्रम पदानुक्रम में एक विशिष्ट वर्ग से एक सदस्य फ़ंक्शन को कॉल करना चाहते हैं, तो हम फ़ंक्शन को कॉल करते समय फ़ंक्शन नाम को योग्य कर सकते हैं, उस वर्ग को नाम से निर्दिष्ट कर सकते हैं।

struct One {
    virtual void f() { std::cout << "One." << std::endl; }
};

struct Two : One {
    void f() override {
        One::f(); // this->One::f();
        std::cout << "Two." << std::endl;
    }
};

struct Three : Two {
    void f() override {
        Two::f(); // this->Two::f();
        std::cout << "Three." << std::endl;
    }
};

// ...

Three t;

t.f();      // Normal syntax.
t.Two::f(); // Calls version of f() defined in Two.
t.One::f(); // Calls version of f() defined in One.

आभासी सदस्य कार्य

सदस्य कार्यों को भी virtual घोषित किया जा सकता है। इस मामले में, अगर किसी सूचक या उदाहरण के संदर्भ में कहा जाता है, तो उन्हें सीधे एक्सेस नहीं किया जाएगा; बल्कि, वे फंक्शन को वर्चुअल फंक्शन टेबल में देखेंगे (वर्चुअल कार्यों के लिए पॉइंटर्स-टू-मेंबर-फ़ंक्शंस की एक सूची, जिसे आमतौर पर vtable या vftable रूप में जाना जाता है), और उदाहरण के डायनामिक के लिए उपयुक्त वर्जन को कॉल करने के लिए उपयोग करें (वास्तविक) प्रकार। यदि फ़ंक्शन को सीधे वर्ग के चर से कहा जाता है, तो कोई लुकअप नहीं किया जाता है।

struct Base {
    virtual void func() { std::cout << "In Base." << std::endl; }
};

struct Derived : Base {
    void func() override { std::cout << "In Derived." << std::endl; }
};

void slicer(Base x) { x.func(); }

// ...

Base b;
Derived d;

Base *pb = &b, *pd = &d; // Pointers.
Base &rb = b, &rd = d;   // References.

b.func();   // Output:  In Base.
d.func();   // Output:  In Derived.

pb->func(); // Output:  In Base.
pd->func(); // Output:  In Derived.

rb.func();  // Output:  In Base.
rd.func();  // Output:  In Derived.

slicer(b);  // Output:  In Base.
slicer(d);  // Output:  In Base.

ध्यान दें कि pd Base* , और rd एक Base& , कॉलिंग func() दोनों कॉल में से किसी एक को Derived::func() जगह Base::func() ; इस वजह से vtable के लिए Derived अपडेट Base::func() के बजाय करने के लिए बात करने के लिए प्रवेश Derived::func() । इसके विपरीत, ध्यान दें कि स्लाइस करने वाले को कैसे पास किया जाता है slicer() हमेशा Base::func() में परिणाम होता है Base::func() कहा जा रहा है, तब भी जब पारित उदाहरण एक Derived ; इस डेटा टुकड़ा करने की क्रिया है, जहां एक गुजर के रूप में जाना कुछ की वजह से है Derived एक में उदाहरण Base पैरामीटर मान द्वारा की भाग renders Derived उदाहरण है कि एक नहीं है Base उदाहरण दुर्गम।

जब किसी सदस्य फ़ंक्शन को वर्चुअल के रूप में परिभाषित किया जाता है, तो सभी हस्ताक्षरित वर्ग सदस्य फ़ंक्शन समान हस्ताक्षर के साथ इसे ओवरराइड करते हैं, भले ही ओवरराइडिंग फ़ंक्शन virtual रूप में निर्दिष्ट किया गया हो या नहीं। यह प्रोग्रामर को पार्स करने के लिए व्युत्पन्न कक्षाएं कठिन बना सकता है, हालांकि, जैसा कि कोई संकेत नहीं है कि कौन सा फ़ंक्शन / s virtual

struct B {
    virtual void f() {}
};

struct D : B {
    void f() {} // Implicitly virtual, overrides B::f.
                //  You'd have to check B to know that, though.
};

ध्यान दें, हालांकि, एक व्युत्पन्न फ़ंक्शन केवल आधार फ़ंक्शन को ओवरराइड करता है यदि उनके हस्ताक्षर मेल खाते हैं; यहां तक कि अगर एक व्युत्पन्न फ़ंक्शन को स्पष्ट रूप से virtual घोषित किया जाता है, तो यह हस्ताक्षर की बेमेल होने पर एक नया आभासी फ़ंक्शन बनाएगा।

struct BadB {
    virtual void f() {}
};

struct BadD : BadB {
    virtual void f(int i) {} // Does NOT override BadB::f.
};
सी ++ 11

C ++ 11 के अनुसार, संदर्भ-संवेदनशील कीवर्ड override साथ ओवरराइड करने का इरादा स्पष्ट किया जा सकता है। यह कंपाइलर को बताता है कि प्रोग्रामर को बेस क्लास फ़ंक्शन को ओवरराइड करने की उम्मीद है, जो कंपाइलर को त्रुटि से बाहर निकलने का कारण बनता है अगर वह कुछ भी ओवरराइड नहीं करता है

struct CPP11B {
    virtual void f() {}
};

struct CPP11D : CPP11B {
    void f() override {}
    void f(int i) override {} // Error: Doesn't actually override anything.
};

इससे प्रोग्रामर को यह बताने में भी लाभ होता है कि फ़ंक्शन दोनों आभासी है, और कम से कम एक आधार वर्ग में भी घोषित किया गया है, जो जटिल कक्षाओं को पार्स करने में आसान बना सकता है।

जब कोई फ़ंक्शन virtual घोषित किया जाता है, और वर्ग परिभाषा के बाहर परिभाषित किया जाता है, तो virtual स्पेसियर को फ़ंक्शन घोषणा में शामिल किया जाना चाहिए, और परिभाषा में दोहराया नहीं जाना चाहिए।

सी ++ 11

यह override लिए भी सही है।

struct VB {
    virtual void f(); // "virtual" goes here.
    void g();
};
/* virtual */ void VB::f() {} // Not here.
virtual void VB::g() {} // Error.

यदि एक बेस क्लास एक virtual फ़ंक्शन को ओवरलोड करता है, तो केवल ओवरलोड जो स्पष्ट रूप से निर्दिष्ट हैं virtual रूप में virtual होगा।

struct BOverload {
    virtual void func() {}
    void func(int) {}
};

struct DOverload : BOverload {
    void func() override {}
    void func(int) {}
};

// ...

BOverload* bo = new DOverload;
bo->func(); // Calls DOverload::func().
bo->func(1); // Calls BOverload::func(int).

अधिक जानकारी के लिए, संबंधित विषय देखें।

लगातार सुधार

this cv- क्वालीफायर के लिए प्राथमिक उपयोगों में से एक const है । यह गारंटी देने की प्रथा है कि किसी वस्तु को संशोधित करने के लिए केवल उस एक्सेस की आवश्यकता होती है जो ऑब्जेक्ट को संशोधित करने में सक्षम हो, और किसी भी (सदस्य या गैर-सदस्य) फ़ंक्शन को किसी ऑब्जेक्ट को संशोधित करने की आवश्यकता नहीं है, जिसमें उस तक पहुंच नहीं है। ऑब्जेक्ट (चाहे प्रत्यक्ष या अप्रत्यक्ष रूप से)। यह अनजाने संशोधनों को रोकता है, जिससे कोड कम त्रुटिपूर्ण हो जाता है। यह किसी भी फ़ंक्शन को अनुमति देता है जो फ़ंक्शन को फिर से लिखने या अधिभार की आवश्यकता के बिना राज्य को संशोधित करने के लिए एक const या गैर- const ऑब्जेक्ट लेने में सक्षम होने की आवश्यकता नहीं है।

const शुद्धता, अपनी प्रकृति के कारण, नीचे से ऊपर में शुरू होता है: किसी भी वर्ग के सदस्य समारोह है कि परिवर्तन राज्य की जरूरत नहीं है है के रूप में घोषित const है, ताकि उस पर कहा जा सकता है const उदाहरणों। यह बदले में, पारित-दर-संदर्भ पैरामीटर को const घोषित करने की अनुमति देता है जब उन्हें संशोधित करने की आवश्यकता नहीं होती है, जो कार्यों को शिकायत के बिना या तो const या गैर- const ऑब्जेक्ट लेने की अनुमति देता है, और इसमें const -नेस बाहर की ओर फैल सकता है तौर तरीका। इस के कारण, टिककर खेल अक्सर हैं const , के रूप में किसी भी अन्य कार्यों है कि तार्किक राज्य संशोधित करने की जरूरत नहीं है।

class ConstIncorrect {
    Field fld;

  public:
    ConstIncorrect(const Field& f) : fld(f) {}     // Modifies.

    const Field& get_field()       { return fld; } // Doesn't modify; should be const.
    void set_field(const Field& f) { fld = f; }    // Modifies.

    void do_something(int i) {                     // Modifies.
        fld.insert_value(i);
    }
    void do_nothing()        { }                   // Doesn't modify; should be const.
};

class ConstCorrect {
    Field fld;

  public:
    ConstCorrect(const Field& f) : fld(f) {}       // Not const: Modifies.

    const Field& get_field() const { return fld; } // const: Doesn't modify.
    void set_field(const Field& f) { fld = f; }    // Not const: Modifies.

    void do_something(int i) {                     // Not const: Modifies.
        fld.insert_value(i);
    }
    void do_nothing() const  { }                   // const: Doesn't modify.
};

// ...

const ConstIncorrect i_cant_do_anything(make_me_a_field());
// Now, let's read it...
Field f = i_cant_do_anything.get_field();
  // Error: Loses cv-qualifiers, get_field() isn't const.
i_cant_do_anything.do_nothing();
  // Error: Same as above.
// Oops.

const ConstCorrect but_i_can(make_me_a_field());
// Now, let's read it...
Field f = but_i_can.get_field(); // Good.
but_i_can.do_nothing();          // Good.

जैसा कि ConstIncorrect और ConstCorrect की टिप्पणियों से ConstIncorrect ConstCorrect , ठीक से ConstCorrect क्वालीफाइंग फ़ंक्शन भी प्रलेखन के रूप में कार्य करता है। यदि एक वर्ग है const सही, किसी भी समारोह है कि नहीं है const सुरक्षित रूप से परिवर्तन राज्य माना जा सकता है, और किसी भी समारोह है कि है const सुरक्षित रूप से परिवर्तन राज्य के लिए नहीं माना जा सकता है।



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow