C ++ में टेम्पलेट क्लास से इनहेरिट करना


106

मान लें कि हमारे पास एक टेम्पलेट वर्ग है Area, जिसमें एक सदस्य चर है T area, T getArea()और एक void setArea(T)सदस्य कार्य करता है।

मैं Areaटाइप करके एक विशिष्ट प्रकार का ऑब्जेक्ट बना सकता हूं Area<int>

अब मेरे पास एक वर्ग है Rectangleजो वर्ग को विरासत में मिला है Area। चूंकि Rectangleखुद कोई टेम्प्लेट नहीं है, इसलिए मैं टाइप नहीं कर सकता Rectangle<int>

मैं वस्तुओं के Areaलिए विरासत में किस प्रकार का विशेषज्ञ हूं Rectangle?

संपादित करें: क्षमा करें, मैं स्पष्ट करना भूल गया - मेरे सवाल यह है कि क्या यह क्षेत्र को विशेषज्ञता के बिना विरासत में प्राप्त करना संभव है, इसलिए यह क्षेत्र के क्षेत्र के रूप में विरासत में नहीं मिला है, लेकिन जैसा कि क्षेत्र आयत के प्रकारों के विशेषज्ञ कर सकते हैं।


3
यह क्लास टेम्प्लेट है , क्योंकि यह एक टेम्प्लेट है जिसमें से क्लासेस जेनरेट की जाती हैं।
sbi

1
@ एसबीआई का यहाँ कोई लौ युद्ध शुरू करने का इरादा नहीं है, लेकिन अगर ब्रेज़ेन स्ट्रॉस्ट्रुप क्लास टेम्पलेट और टेम्प्लेट क्लास के बीच कोई अंतर नहीं करता है (देखें सी ++ प्रोग्रामिंग लैंग्वेज , 4 थ एड।, सेक्शन 23.2.1), तो आप नहीं जानते। 'या तो।
माइकल वॉर्नर

@MichaelWarner मुझे लगता है कि उसे भेद करने के लिए याद करते हैं। यह 90 के दशक में था, हालांकि, यूज़नेट पर। शायद उसने हार मान ली है। (या हो सकता है कि वह तात्कालिक वर्ग के खाके को खाका वर्ग के रूप में संदर्भित करता है?)
sbi

जवाबों:


244

टेम्प्लेट को समझने के लिए, शब्दावली को सीधे प्राप्त करने के लिए यह बहुत बड़ा लाभ है क्योंकि आप उनके बारे में बोलने का तरीका उनके बारे में सोचने का तरीका निर्धारित करते हैं।

विशेष रूप से, Areaटेम्प्लेट क्लास नहीं है, बल्कि क्लास टेम्प्लेट है। यही है, यह एक टेम्पलेट है जिसमें से कक्षाएं उत्पन्न की जा सकती हैं। Area<int>एक ऐसी कक्षा है (यह एक वस्तु नहीं है , लेकिन निश्चित रूप से आप उस वर्ग से एक वस्तु बना सकते हैं उसी तरह से आप किसी अन्य वर्ग से ऑब्जेक्ट बना सकते हैं)। एक और ऐसा वर्ग होगा Area<char>। ध्यान दें कि वे पूरी तरह से अलग वर्ग हैं, जिनके पास समान तथ्य के अलावा कुछ भी नहीं है कि वे एक ही वर्ग टेम्पलेट से उत्पन्न हुए थे।

चूँकि Areaकोई वर्ग नहीं है, आप वर्ग Rectangleको इससे प्राप्त नहीं कर सकते । आप केवल एक कक्षा को दूसरे वर्ग (या उनमें से कई) से प्राप्त कर सकते हैं। चूंकि Area<int>एक वर्ग है, आप उदाहरण के लिए, इससे प्राप्त Rectangleकर सकते हैं:

class Rectangle:
  public Area<int>
{
  // ...
};

चूंकि Area<int>और Area<char>अलग-अलग वर्ग हैं, आप एक ही समय में दोनों से प्राप्त कर सकते हैं (हालांकि जब उनके सदस्यों को एक्सेस करना है, तो आपको अस्पष्टताओं से निपटना होगा):

class Rectangle:
  public Area<int>,
  public Area<char>
{
  // ...
};

हालांकि आपको यह निर्दिष्ट करना होगा कि आप परिभाषित करते समय किस वर्ग से प्राप्त करें Rectangle। यह सच है कि कोई फर्क नहीं पड़ता कि उन वर्गों को एक टेम्पलेट से उत्पन्न किया जाता है या नहीं। एक ही वर्ग की दो वस्तुओं में अलग-अलग वंशानुगत पदानुक्रम नहीं हो सकते।

आप जो भी कर सकते हैं, वह Rectangleएक टेम्पलेट बनाना है। अगर आप लिखेंगे

template<typename T> class Rectangle:
  public Area<T>
{
  // ...
};

आपके पास एक टेम्प्लेट Rectangleहै जिसमें से आप एक क्लास प्राप्त कर सकते हैं Rectangle<int>जो व्युत्पन्न करता है Area<int>, और एक अलग वर्ग Rectangle<char>जो व्युत्पन्न करता है Area<char>

यह हो सकता है कि आप एक ही प्रकार का होना चाहते हैं Rectangleताकि आप Rectangleएक ही फ़ंक्शन के सभी प्रकार पास कर सकें (जो खुद को एरिया प्रकार जानने की आवश्यकता नहीं है)। चूँकि Rectangle<T>टेम्पलेट Rectangleको तात्कालिक बनाने से उत्पन्न कक्षाएं औपचारिक रूप से एक दूसरे से स्वतंत्र होती हैं, इसलिए यह उस तरह से काम नहीं करती है। हालाँकि आप यहाँ कई उत्तराधिकार का उपयोग कर सकते हैं:

class Rectangle // not inheriting from any Area type
{
  // Area independent interface
};

template<typename T> class SpecificRectangle:
  public Rectangle,
  public Area<T>
{
  // Area dependent stuff
};

void foo(Rectangle&); // A function which works with generic rectangles

int main()
{
  SpecificRectangle<int> intrect;
  foo(intrect);

  SpecificRectangle<char> charrect;
  foo(charrect);
}

यदि यह महत्वपूर्ण है कि आपका जेनेरिक जेनेरिक Rectangleसे लिया गया है, Areaतो आप उसी चाल को Areaभी कर सकते हैं :

class Area
{
  // generic Area interface
};

class Rectangle:
  public virtual Area // virtual because of "diamond inheritance"
{
  // generic rectangle interface
};

template<typename T> class SpecificArea:
  public virtual Area
{
  // specific implementation of Area for type T
};

template<typename T> class SpecificRectangle:
  public Rectangle, // maybe this should be virtual as well, in case the hierarchy is extended later
  public SpecificArea<T> // no virtual inheritance needed here
{
  // specific implementation of Rectangle for type T
};

नोट: एक टेम्प्लेट टाइप पैरामीटर किसी ऑब्जेक्ट के क्लास का हिस्सा होता है, जो उस क्लास टेम्पलेट को इंस्टेंट करता है। दूसरे शब्दों में, यह कक्षा का एक घटक नहीं है, यह प्रकार का हिस्सा है।
निकोस

21

क्या आप अभी प्राप्त करने की कोशिश कर रहे हैं Area<int>? किस मामले में आप ऐसा करते हैं:

class Rectangle : public Area<int>
{
    // ...
};

संपादित करें: स्पष्टीकरण के बाद, ऐसा लगता है कि आप वास्तव में Rectangleएक टेम्पलेट बनाने की कोशिश कर रहे हैं , जिस स्थिति में निम्नलिखित काम करना चाहिए:

template <typename T>
class Rectangle : public Area<T>
{
    // ...
};


8

आयत को एक टेम्प्लेट बनाएं और टाइपनाम को क्षेत्र में पास करें:

template <typename T>
class Rectangle : public Area<T>
{

};

6

Rectangleएक टेम्पलेट बनना होगा, अन्यथा यह सिर्फ एक प्रकार है । यह एक गैर-टेम्पलेट नहीं हो सकता है जबकि इसका आधार जादुई रूप से है। (इसका आधार टेम्पलेट तात्कालिकता हो सकता है , हालाँकि आप आधार की कार्यक्षमता को टेम्पलेट के रूप में बनाए रखना चाहते हैं ।)


3
#include<iostream>

using namespace std;

template<class t> 
class base {
protected:
    t a;
public:
    base(t aa){
        a = aa;
        cout<<"base "<<a<<endl;
    }
};

template <class t> 
class derived: public base<t>{
    public:
        derived(t a): base<t>(a) {
        }
        //Here is the method in derived class 
    void sampleMethod() {
        cout<<"In sample Method"<<endl;
    }
};

int main() {
    derived<int> q(1);
    // calling the methods
    q.sampleMethod();
}

क्या होगा यदि आपके पास व्युत्पन्न वर्ग में विधियां हैं? आप उन्हें कैसे परिभाषित करेंगे? और सबसे आयात अभी तक, कम से कम मेरे लिए, आप अपने मुख्य () फ़ंक्शन में उन तरीकों को कैसे कॉल / उपयोग करते हैं?
पोटोटो

6
पहला, यह वास्तव में पुराना सवाल है जिसका पहले से ही बहुत अच्छा जवाब है। दूसरा, कृपया उत्तर (और प्रश्न) से बचें जो केवल कोड हैं। विस्तृत विवरणों को भी शामिल करना उपयोगी है।
जूल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.