2010-04-26 20 views
8

विजुअल स्टूडियो 2008 में, संकलक नीचे _tmain में SetCustomer करने के लिए कॉल को हल नहीं कर सकता है और यह स्पष्ट हो जाता है:अस्पष्ट पहुँच

// error C2385: ambiguous access of 'SetConsumer' 
// could be the 'SetConsumer' in base 'Producer<AppleConsumer>' 
// or could be the 'SetConsumer' in base 'Producer<MeatConsumer>' 
:

template <typename TConsumer> 
struct Producer 
{ 
    void SetConsumer(TConsumer* consumer) { consumer_ = consumer; } 

    TConsumer* consumer_; 
}; 

struct AppleConsumer 
{ 
}; 

struct MeatConsumer 
{ 
}; 

struct ShillyShallyProducer : public Producer<AppleConsumer>, 
           public Producer<MeatConsumer> 
{ 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    ShillyShallyProducer producer; 
    AppleConsumer consumer; 
    producer.SetConsumer(&consumer); // <--- Ambiguous call!! 

    return 0; 
} 

यह संकलन त्रुटि है

मैंने सोचा था कि टेम्पलेट तर्क लुकअप तंत्र सही आधार Producer को कम करने के लिए पर्याप्त स्मार्ट होगा। यह क्यों नहीं है

मैं इस के आसपास

template <typename TConsumer> 
struct Producer 
{ 
    template <typename TConsumer2> 
    void SetConsumer(TConsumer2* consumer) { consumer_ = consumer; } 

    TConsumer* consumer_; 
}; 

को Producer बदलकर हो और कह सकते हैं SetConsumer रूप

producer.SetConsumer<AppleConsumer>(&consumer); // Unambiguous call!! 

लेकिन यह अगर मैं नहीं था अच्छे होगा ...

+0

मैं सिर्फ बाहर बिंदु करना चाहते हैं कि आपके प्रस्तावित कार्यवाही में, आपको 'SetConsumer (& उपभोक्ता)', 'SetConsumer (& उपभोक्ता)' को कॉल करने की आवश्यकता नहीं है, और पर्याप्त रूप से टेम्पलेट तर्क को कम करेगा)। – sbk

+0

@ एसबीके: नहीं, यह नहीं होगा। मैंने पोस्ट करने से पहले कोशिश की, और अब एक बार फिर से सुनिश्चित हो। अभी भी अस्पष्ट –

उत्तर

12

I thought the template argument lookup mechanism would be smart enough to deduce the correct base Producer.

यह टेम्पलेट्स के साथ क्या करना नहीं है, यह एक से अधिक आधार वर्ग का उपयोग कर से आता है - नाम देखने को पहले से ही अस्पष्ट है और अधिभार संकल्प केवल लेता है उसके बाद जगह

एक सरलीकृत उदाहरण होगा निम्नलिखित:

struct A { void f() {} }; 
struct B { void f(int) {} }; 
struct C : A, B {}; 

C c; 
c.f(1); // ambiguous 

समाधान स्पष्ट रूप से कॉल योग्यता रहे हैं या व्युत्पन्न वर्ग दायरे में कार्यों को लागू करना:

struct ShillyShallyProducer : public Producer<AppleConsumer>, 
           public Producer<MeatConsumer> 
{ 
    using Producer<AppleConsumer>::SetConsumer; 
    using Producer<MeatConsumer >::SetConsumer; 
}; 
+0

@gf: "व्युत्पन्न कक्षाओं के क्षेत्र में कार्यों को पेश करें" - यह एक अच्छा समाधान है, क्योंकि जब भी मैं एक नया उत्पादित उत्पाद जोड़ता हूं तो मैं निर्माता क्लाइंट कॉल साइट को बदलना नहीं चाहता हूं। प्रेमपूर्ण धन्यवाद! –

2

आप बस अपने फ़ंक्शन कॉल में स्पष्ट योग्यता का उपयोग कर सकते हैं। बजाय:

producer.SetConsumer(&consumer); 

कोशिश:

producer.Producer<AppleConsumer>::SetConsumer(&consumer); 
संबंधित मुद्दे