2009-09-24 9 views
26

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

void MyFunction(ClassParam mClass) 
{ 
    mClass *tmp = new mClass(); 
} 

उपर्युक्त वास्तविक कोड नहीं है, लेकिन उम्मीद है कि मैं एक उदाहरण में क्या करने की कोशिश कर रहा हूं।

उत्तर

37

आप समान (लेकिन वास्तव में) कुछ हासिल करने के लिए टेम्पलेट का उपयोग कर सकते हैं के लिए देख रहे हैं:

template<class T> 
void MyFunction() 
{ 
    T *tmp = new T(); 
} 

और MyFunction<MyClassName>() से कॉल करने की।

ध्यान दें कि इस तरह, आप T के स्थान पर "चर" का उपयोग नहीं कर सकते हैं। यह संकलन समय पर जाना जाना चाहिए।

19

सी ++ अन्य भाषाओं के रूप में वर्गों के बारे में मेटा डेटा स्टोर नहीं करता है।

template <typename T> 
void MyFunction() 
{ 
    T* p = new T; 
} 
+0

अन्य lanaguages ​​के रूप में सभी भाषाओं प्रोग्राम के बारे में मेटा डेटा स्टोर नहीं करते हैं। यह आधुनिक भाषाओं की अपेक्षाकृत नई सुविधा है। –

+1

@ मार्टिन, यह "अपेक्षाकृत नया" की एक दिलचस्प परिभाषा है, जो कि स्मॉलटाक पर विचार कर रही थी, जो कि अपने समय में काफी मुख्यधारा थी, और इसमें बहुत कुछ कोड लिखा गया था, बस 70 के दशक में :) –

+1

कई लोगों के साथ स्मॉलटाक को जिम्मेदार चीजें, लिस्प 1 9 50 के दशक में थी - पूरा कार्यक्रम एक डेटास्ट्रक्चर था जिसका निरीक्षण और छेड़छाड़ की जा सकती थी। –

0

आप अपने वर्ग (ते) पर एक स्थिर कारखाने विधि बना सकते हैं कि बस का एक नया उदाहरण प्रस्तुत करती है: यह मानते हुए कि आप हमेशा एक parameterless निर्माता के साथ एक वर्ग का उपयोग करें, आप एक ही बात को प्राप्त करने के टेम्पलेट का उपयोग कर सकते हैं कक्षा और फिर आप उस फ़ंक्शन पर पॉइंटर्स को अपने उदाहरण में वही कर सकते हैं जो आप अपने उदाहरण में करना चाहते हैं। रिटर्न प्रकार कॉन्वर्सेंट हैं, इसलिए यदि आपके सभी वर्ग एक ही इंटरफ़ेस को लागू करते हैं, तो आप फ़ंक्शन पॉइंटर उस इंटरफ़ेस को वापस कर सकते हैं। यदि उनके पास एक सामान्य इंटरफ़ेस नहीं है, तो आपको शायद void * लौटने के साथ छोड़ा जाएगा। किसी भी तरह से, यदि आपको विशिष्ट उप-वर्ग का उपयोग करने की आवश्यकता है, तो आपको dynamic_cast करना होगा।

2

आप एक फ़ंक्शन पॉइंटर में भी पास कर सकते हैं जिसे कॉल किया जाता है जब भी आप जो चाहते हैं उसका एक उदाहरण बनाता है और उसे वापस कर देता है।

void MyFunction(ClassCreatorPtr makeClassFn) 
{ 
    void * myObject = makeClassFn(); 
} 

आपको इसके साथ वास्तव में दिलचस्प कुछ भी करने के लिए बेस क्लास में एक पॉइंटर वापस करना होगा।

0

टेम्पलेट्स का एक विकल्प सी ++ 11 के साथ लैम्ब्डा क्लोजर का उपयोग करना है। मेरी वरीयता यहाँ है।

// in header file 
IClass * MyFunctionThatDoesStuff(const IParams & interface_params, 
    std::function<IClass * (const IParams & interface_params)> cls_allocator); 

// in source file 
IClass * MyFunctionThatDoesStuff(const IParams & interface_params, 
    std::function<IClass * (const IParams & interface_params)> cls_allocator) { 
    // Some processing. Perhaps the interface_params are generated 
    // inside this function instead of being passed to it. 
    IClass * mCls = cls_allocator(interface_params); 
    // Do whatever with mCls 
    return mCls; 
} 

// Somewhere else in the code. 
{ 
    Param1Type param1 = whatever1; 
    Param2Type param1 = whatever2; 
    // param1, param2, etc. are parameters that only 
    // SomeClsDerivedFromIClass constructor knows about. The syntax &param1 
    // achieves the closure. 
    // interface_param1 is common to all classes derived from IClass. 
    // Could more than one parameter. These parameters are parameters that 
    // vary from different calls of MyFunctionThatDoesStuff in different 
    // places. 
    auto cls_allocator = 
     [&param1, &param2](const IParams & interface_params)->IClass * { 
      return new SomeCls1DerivedFromIClass(interface_params, 
       param1, param2); 
     }; 
    IClass * mCls = MyFunctionThatDoesStuff(interface_params, 
     cls_allocator); 
} 

// Somewhere else in the code again. 
{ 
    ParamXType paramX = whateverX; 
    ParamYType paramY = whateverY; 
    auto cls_allocator = 
     [&paramX, &paramY](const IParams & interface_params)->IClass * { 
      return new SomeCls2DerivedFromIClass(interface_params, 
       paramX, paramY); 
     }; 
    IClass * mCls = MyFunctionThatDoesStuff(interface_params, 
     cls_allocator); 
} 

ऊपर कोड विचार एक त्वरित बिल्डर पैटर्न या कुछ कारखाने पैटर्न बदलाव के लिए अच्छी तरह से काम करता है। लैम्ब्डा मूल रूप से एक कारखाना विधि है। इसे और भी गतिशील बनाने के लिए आप पैरामीटर टाइपिंग के लिए ऑटो का उपयोग कर सकते हैं। कुछ इस तरह।

auto * MyFunctionThatDoesStuff(const auto & interface_params, 
    std::function<auto * (const auto & interface_params)> cls_allocator); 

मैं अजगर प्रभाव जहां सिर्फ कार्य करने के लिए वर्ग प्रकार पारित कर सकते हैं इस पर आ रहा हूँ।

संबंधित मुद्दे