2017-09-07 14 views
17

मैं सी में लिख रहा हूँ ++ और मैं एक अज्ञात प्रकार (केवल रन समय में जाना जाता है) एक शुद्ध आभासी समारोह को पास करना चाहते करने के लिए अज्ञात प्रकार गुजर:सी ++ एक आभासी समारोह

virtual void DoSomething(??? data); 

जहां DoSomething एक कार्यान्वयन है व्युत्पन्न वर्ग में शुद्ध वर्चुअल फ़ंक्शन का।

मैं टेम्पलेट का उपयोग करने की योजना बनाई है, लेकिन के रूप में यह आभासी समारोह बाहर कर देते हैं और टेम्पलेट्स एक साथ काम नहीं करते: Can a C++ class member function template be virtual?

मैं (object की तरह कुछ सभी वर्गों मैं समारोह को पारित करने के लिए एक आधार वर्ग का उपयोग कर से बचना चाहते हैं सी # में)।

अग्रिम धन्यवाद

+1

आप कृपया अधिक विशिष्ट हो सकता है

आप आगंतुक पैटर्न का उपयोग करने के लिए दिलचस्पी हो सकती है? आप फ़ंक्शन के अंदर डेटा का उपयोग कैसे करते हैं? डेटा के प्रकार के लिए क्या आवश्यकताएं हैं? जैसे केवल कुछ ज्ञात वर्ग हैं, या आप किसी भी वर्ग को स्वीकार करने की योजना बना रहे हैं जिसमें एक विशिष्ट विधि आदि है? – bolov

+1

आपके प्रश्न को थोड़ा सा संकुचित करने की आवश्यकता है। क्या आप प्रकार की रेंज जानते हैं, क्या आप चाहते हैं कि उन्हें स्वचालित रूप से घटाया जाए? सबसे आसान जवाब "शून्य का उपयोग करें" होगा, एक बेहतर उत्तर स्टोरी टेलर में से एक हो सकता है। यह सब आपके उपयोगकेस पर निर्भर करता है। –

+0

मैं उत्सुक हूं, जवाब देख रहा हूं, अगर किसी भी परिणाम को 'doSomething' पर कोई कास्टिंग किए बिना प्राप्त करने की कोई संभावना है। कुछ ऐसा तरीके से प्रकार को encapsulating जैसे कुछ 'टेम्पलेट' करने के बिना, और उस प्रकार को 'decltype'' के साथ पुनर्प्राप्त करने के बिना, यानी एक वर्चुअल फैक्ट्री विधि की तरह ... – perencia

उत्तर

18

में आप type erasure की जरूरत है। इसका एक उदाहरण सामान्य उद्देश्य boost::any (और std::any सी ++ में) है।

virtual void DoSomething(boost::any const& data); 

और फिर प्रत्येक उप वर्ग आदेश डेटा यह उम्मीद प्राप्त करने के लिए सुरक्षितany_cast प्रयास कर सकते हैं।

void DoSomething(boost::any const& data) { 
    auto p = any_cast<std::string>(&data); 

    if(p) { 
    // do something with the string pointer we extracted 
    } 
} 

आप निश्चित रूप से अपने स्वयं के प्रकार मिटाने का काम अमूर्त बाहर रोल कर सकते हैं, तो व्यवहार की सीमा आप की तलाश अधिक विवश है।

0

कुछ है कि जैसे ?:

class Foo 
{ 
    virtual ~Foo() = 0; 
}; 

template <typename T> 
class Bar : public Foo 
{ 
    T object; 
} 

... 

virtual void DoSomething(Foo* data) 
{ 
    Bar<int>* temp = dynamic_cast<Bar<int>*>(data); 
    if (temp) 
     std::count<<temp->object; 
} 
+6

'फू' को कम से कम एक वर्चुअल सदस्य फ़ंक्शन (शायद विनाशक) की आवश्यकता है, अन्यथा 'dynamic_cast' काम नहीं करेगा। – Angew

+0

'मैं फ़ंक्शन में पास की जाने वाली सभी कक्षाओं (सी # में ऑब्जेक्ट की तरह कुछ) के लिए बेस क्लास का उपयोग करना टालना चाहता हूं। – perencia

+0

इस फ़ंक्शन में पारित प्रत्येक ऑब्जेक्ट के लिए बेस क्लास की आवश्यकता नहीं है, केवल रैपर के लिए' Bar'। हालांकि यह तकनीकी रूप से 'ऑब्जेक्ट पास किया गया' है, यह ओपी का मतलब होने की संभावना नहीं है। – AzCopey

1

आप को बढ़ावा देने का उपयोग नहीं करना चाहते हैं/C++ 17 किसी भी, एक आधार वर्ग से 'doSometing' समारोह के पैरामीटर पाने पर विचार करें, और करने के लिए गतिशील डाली करना सही वर्ग वस्तु। इस मामले में आप रनटाइम में जांच सकते हैं कि आपको एक वैध सूचक मिला है।

class param{ 
public: 
    virtual ~param(){}; 
}; 

template <typename T> 
struct specificParam:param{ 
    specificParam(T p):param(p){} 
    T param; 
}; 


class Foo 
{ 
public: 
    virtual void doSomething(param* data) = 0; 
}; 

template <typename T> 
class Bar : public Foo 
{ 
public: 
    virtual void doSomething(param* data){ 
     specificParam<T> *p = dynamic_cast<specificParam<T> *>(data); 

     if (p != nullptr){ 
      std::cout<<"Bar got:" << p->param << "\n"; 
     } 
     else { 
      std::cout<<"Bar: parameter type error.\n"; 
     } 
    } 
}; 

int main(){ 
    Bar<char> obj1; 
    Bar<int> obj2; 
    Bar<float> obj3; 

    specificParam<char> t1('a'); 
    specificParam<int> t2(1); 
    specificParam<float> t3(2.2); 

    obj1.doSomething(&t1); //Bar got:a 
    obj2.doSomething(&t2); //Bar got:1 
    obj3.doSomething(&t3); //Bar got:2.2 

    // trying to access int object with float parameter 
    obj2.doSomething(&t3); //Bar: parameter type error. 
} 

सरल (लेकिन असुरक्षित!) जिस तरह से उपयोग करने के लिए शून्य * सूचक + स्थिर डाली

class Foo 
{ 
public: 
    virtual void doSomething(void* data) = 0; 
}; 

template <typename T> 
class Bar:public Foo 
{ 
public: 
    virtual void doSomething(void* data){ 
     T* pData = static_cast<T*>(data); 
     std::cout<<"Bar1 got:" << *pData << "\n"; 
    } 
}; 

int main(){ 

    Bar<char> obj1; 
    Bar<int> obj2; 
    Bar<float> obj3; 

    char c = 'a'; 
    int i = 1; 
    float f = 2.2; 

    obj1.doSomething(&c); // Bar1 got:a 
    obj2.doSomething(&i); // Bar1 got:1 
    obj3.doSomething(&f); // Bar1 got:2.2 

    //obj2.doSomething(&c); // Very bad!!!  
} 
1

टाइप-विलोपन केवल संभावना नहीं है किया जाएगा। तर्क के रूप में लेने के लिए एक std :: संस्करण और एक लैम्ब्डा टेम्पलेट कोड क्रियान्वित करना चाहते थे जिसमें वह यह जाएँ::

virtual void doSomething(std::variant<int,float/*,...*/> data) 
    { 
    visit([=](auto v){/*...*/;},data); 
    } 
संबंधित मुद्दे