मैं व्युत्पन्न वर्ग निर्माता में आधार वर्ग के सदस्य चर को कैसे आरंभ कर सकता हूं?


123

मैं ऐसा क्यों नहीं कर सकता?

class A
{
public:
    int a, b;
};

class B : public A
{
    B() : A(), a(0), b(0)
    {
    }

};

7
क्या आप पूछ रहे हैं कि आप ऐसा क्यों नहीं कर सकते हैं, जो भाषा-डिज़ाइन का प्रश्न है, या आप पूछ रहे हैं कि उस भाषा सीमा के आसपास कैसे काम करें?
रॉब केनेडी

मैंने सोचा था कि यह करने के लिए एक विशेष तरीके का कुछ प्रकार था जो मुझे पता नहीं है, बिना आधार निर्माणकर्ता का उपयोग किए बिना।
अमृतसैन

आपके व्युत्पन्न वर्ग निर्माता को चलाने के लिए आधार वर्ग के सदस्यों को पहले से ही आरंभिक कर दिया जाता है। आप उन्हें असाइन कर सकते हैं , यदि आपके पास उनके लिए एक्सेस या कॉल सेटर्स हैं, या आप उनके लिए बेस क्लास कंस्ट्रक्टर को वैल्यू दे सकते हैं, अगर कोई उपयुक्त है। एक चीज जो आप तैयार वर्ग में नहीं कर सकते, उन्हें इनिशियलाइज़ करें।
लोर्न

जवाबों:


143

आप प्रारंभ नहीं कर सकते हैं aऔर bमें Bहै क्योंकि वे के सदस्य नहीं हैं B। वे सदस्य हैं A, इसलिए केवल Aउन्हें आरंभ कर सकते हैं। आप उन्हें सार्वजनिक कर सकते हैं, फिर असाइनमेंट कर सकते हैं B, लेकिन यह अनुशंसित विकल्प नहीं है क्योंकि यह एनकैप्सुलेशन को नष्ट कर देगा। इसके बजाय, उन्हें आरंभ Aकरने के लिए B(या किसी भी उपवर्ग A) की अनुमति देने के लिए एक निर्माता बनाएँ :

class A 
{
protected:
    A(int a, int b) : a(a), b(b) {} // Accessible to derived classes
    // Change "protected" to "public" to allow others to instantiate A.
private:
    int a, b; // Keep these variables private in A
};

class B : public A 
{
public:
    B() : A(0, 0) // Calls A's constructor, initializing a and b in A to 0.
    {
    } 
};

32
जबकि आपका उदाहरण सही है, आपका स्पष्टीकरण भ्रामक है। यह नहीं है कि आप नहीं कर सकते हैं प्रारंभ a और bमें B::B(), क्योंकि वे निजी हैं। आप उन्हें प्रारंभ नहीं कर सकते क्योंकि वे सदस्य नहीं हैं class B। यदि आपने उन्हें सार्वजनिक या संरक्षित किया है तो आप उन्हें निकाय में दे सकते हैंB::B()
आर सैमुअल क्लैत्को

2
इसके अतिरिक्त, आप समाधान को ए-ए-एग्रीगेट बनाते हैं, जो महत्वपूर्ण हो सकता है, इसलिए इसका उल्लेख किया जाना चाहिए।
Gene बजे जीन बुशुइव

1
@ आर सैमुअल क्लैचको: अच्छी बात है। जब मैं जवाब लिख रहा था, तो मैंने शुरू में "आप एक्सेस नहीं कर सकते ... aऔर b" और इसे "आप इनिशियलाइज़ नहीं कर सकते ..." को बदल दिया, यह सुनिश्चित किए बिना कि बाकी वाक्य समझ में आए। पोस्ट संपादित किया गया।
सिलिको में

1
@Gene Bushuyev: प्रश्न में मूल कोड में वर्ग एक समुच्चय नहीं है (गैर-स्थिर निजी सदस्य हैं)
डेविड रॉड्रिग्ज - dribeas

@ डेविड - सही है, जो एक उपयोगकर्ता की त्रुटि है, और मैं उपयोगकर्ता के इरादों को प्राप्त करने की कोशिश कर रहा हूं, सतही लंघन।
जीन बुशुयेव

26

इस तथ्य को छोड़ते हुए कि वे हैं private, चूंकि aऔर के bसदस्य हैं A, उनका मतलब Aकुछ अन्य वर्ग के निर्माणकर्ताओं द्वारा व्युत्पन्न किया जाना है (व्युत्पन्न या नहीं)।

प्रयत्न:

class A
{
    int a, b;

protected: // or public:
    A(int a, int b): a(a), b(b) {}
};

class B : public A
{
    B() : A(0, 0) {}
};

7

किसी तरह, किसी ने सबसे सरल तरीका सूचीबद्ध नहीं किया:

class A
{
public:
    int a, b;
};

class B : public A
{
    B()
    {
        a = 0;
        b = 0;
    }

};

आप प्रारंभकर्ता सूची में पहुँच आधार सदस्यों नहीं कर सकते हैं, लेकिन निर्माता ही है, किसी भी अन्य सदस्य पद्धति के रूप में, का उपयोग कर सकते publicहैं और protectedआधार वर्ग के सदस्य।


1
अच्छा लगा। क्या इस तरह से करने में कोई कमी है?
वांडर 3r

2
@ सैलेशडी: यदि आप किसी वस्तु का निर्माण किसी महंगे कंस्ट्रक्टर के साथ कर रहे हैं, तो हो सकता है। यह पहली बार डिफॉल्ट-इनिशियलाइज्ड होगा जब इसका उदाहरण Bआवंटित किया जाता है, तो इसे Bकंस्ट्रक्टर के अंदर सौंपा जाएगा । लेकिन मुझे यह भी लगता है कि कंपाइलर अभी भी इसे ऑप्टिमाइज़ कर सकता है।
वायलेट जिराफ

1
अंदर class Aहम पर भरोसा नहीं किया जा सकता है aऔर bप्रारंभिक किया जा रहा है। class C : public Aउदाहरण के लिए, किसी भी क्रियान्वयन को कॉल करना a=0;और aअनधिकृत रूप से छोड़ना भूल सकते हैं ।
स्पार्कफॉस्का डेका

@Sparkofska, बहुत सच। फ़ील्ड ( class A { int a = 0;};या) या बेस क्लास के कंस्ट्रक्टर में घोषित करते समय फ़ील्ड्स को डिफ़ॉल्ट रूप से या तो इन-प्लेस करना सबसे अच्छा है । उप-वर्ग अभी भी आवश्यकतानुसार उनके निर्माणकर्ता में फिर से शुरू कर सकते हैं।
वायलेट जिराफ

1
@ Wander3r एक और दोष यह है कि सभी वर्गों के पास असाइनमेंट ऑपरेटर नहीं हैं। कुछ का निर्माण केवल किया जा सकता है, लेकिन सौंपा नहीं जा सकता। तो आप कर रहे हैं ...
मार्टिन Pecka

2
# include<stdio.h>
# include<iostream>
# include<conio.h>

using namespace std;

class Base{
    public:
        Base(int i, float f, double d): i(i), f(f), d(d)
        {
        }
    virtual void Show()=0;
    protected:
        int i;
        float f;
        double d;
};


class Derived: public Base{
    public:
        Derived(int i, float f, double d): Base( i, f, d)
        {
        }
        void Show()
        {
            cout<< "int i = "<<i<<endl<<"float f = "<<f<<endl <<"double d = "<<d<<endl;
        }
};

int main(){
    Base * b = new Derived(10, 1.2, 3.89);
    b->Show();
    return 0;
}

यदि आप व्युत्पन्न वर्ग ऑब्जेक्ट में मौजूद बेस क्लास डेटा सदस्यों को इनिशियलाइज़ करना चाहते हैं, तो यह एक कार्यशील उदाहरण है, जबकि आप इन मानों को Derived क्लास कंस्ट्रक्टर कॉल के माध्यम से इंटरफेस करना चाहते हैं।


1

हालांकि यह दुर्लभ मामलों में उपयोगी है (यदि ऐसा नहीं था, तो भाषा ने इसे सीधे अनुमति दी होगी), सदस्य मुहावरे से आधार पर एक नज़र डालें । यह एक कोड मुक्त समाधान नहीं है, आपको विरासत की एक अतिरिक्त परत जोड़ना होगा, लेकिन यह काम पूरा कर लेता है। बॉयलरप्लेट कोड से बचने के लिए आप बूस्ट के कार्यान्वयन का उपयोग कर सकते हैं


0

आप ऐसा क्यों नहीं कर सकते? क्योंकि भाषा आपको शुरुआती वर्ग की प्रारंभिक सूची में आधार वर्ग के सदस्यों को इनिज़ा देने की अनुमति नहीं देती है।

आप यह कैसे कर सकते हैं? ऐशे ही:

class A
{
public:
    A(int a, int b) : a_(a), b_(b) {};
    int a_, b_;
};

class B : public A
{
public:
    B() : A(0,0) 
    {
    }
};

-1

यदि आप एक वर्ग के सदस्य के लिए दृश्यता निर्दिष्ट नहीं करते हैं, तो यह "निजी" के लिए चूक है। यदि आप उन्हें उपवर्ग में एक्सेस करना चाहते हैं तो आपको अपने सदस्यों को निजी या संरक्षित करना चाहिए।


-1

अपने उदाहरण (*) में ए की तरह अलग कक्षाएं, उनके सदस्यों को सार्वजनिक होना चाहिए, और कोई उपयोगकर्ता-परिभाषित निर्माता नहीं होना चाहिए। उन्हें इनिशियल लिस्ट, उदाहरण के लिए A a {0,0};या आपके मामले में सूचित किया जाता है B() : A({0,0}){}। बेस एग्रीगेट वर्ग के सदस्यों को व्युत्पन्न वर्ग के निर्माता में व्यक्तिगत रूप से आरंभीकृत नहीं किया जा सकता है।

(*) सटीक होने के लिए, जैसा कि सही ढंग से उल्लेख किया गया था, class Aनिजी गैर-स्थैतिक सदस्यों के कारण मूल एक समुच्चय नहीं है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.