2012-09-26 24 views
6

तो मेरे पास कोई अमूर्त आधार वर्ग नहीं है जिसमें कोई सार तत्व नहीं है। आदेश अमूर्तता को लागू करने में, मैं (गैर तुच्छ) नाशक घोषित कर दिया है के रूप में शुद्ध आभासी:शुद्ध आभासी विरासत, एकाधिक विरासत, और सी 4505

class AbstractClass 
{ 
public: 
    AbstractClass() 
    { 
    std::wcout << L"AbstractClass::AbstractClass()" << std::endl; 
    } 
    virtual ~AbstractClass() = 0 
    { 
    std::wcout << L"AbstractClass::~AbstractClass()" << std::endl; 
    } 
}; 

class ConcreteClass : public AbstractClass 
{ 
public: 
    ConcreteClass() 
    { 
    std::wcout << L"ConcreteClass::ConcreteClass()" << std::endl; 
    } 
    virtual ~ConcreteClass() 
    { 
    std::wcout << L"ConcreteClass::~ConcreteClass()" << std::endl; 
    } 
}; 

यह बनाता है और अपेक्षा के अनुरूप काम करता है; एक कोड ब्लॉक कि बस ConcreteClass का एक उदाहरण को परिभाषित करता है के लिए उत्पादन

 

    AbstractClass::AbstractClass() 
    ConcreteClass::ConcreteClass() 
    ConcreteClass::~ConcreteClass() 
    AbstractClass::~AbstractClass() 

है अब, जब मैं एक इंटरफ़ेस वर्ग के रूप में इस्तेमाल अन्य वर्ग से AbstractClass निकाले जाते है, जो अपने आप होने एक (तुच्छ) आभासी नाशक (शुद्ध या अन्यथा) , यह अभी भी काम करता है:

class IAlpha 
{ 
public: 
    virtual ~IAlpha() = 0 {} 
}; 

class AbstractClass : public IAlpha 
{ 
public: 
    AbstractClass() 
    { 
    std::wcout << L"AbstractClass::AbstractClass()" << std::endl; 
    } 
    virtual ~AbstractClass() = 0 
    { 
    std::wcout << L"AbstractClass::~AbstractClass()" << std::endl; 
    } 
}; 

class ConcreteClass : public AbstractClass 
{ 
public: 
    ConcreteClass() 
    { 
    std::wcout << L"ConcreteClass::ConcreteClass()" << std::endl; 
    } 
    virtual ~ConcreteClass() 
    { 
    std::wcout << L"ConcreteClass::~ConcreteClass()" << std::endl; 
    } 
}; 

समस्या पैदा होती है जब मैं इस तरह से दो अलग अलग इंटरफेस को लागू करने का प्रयास: इस बिंदु पर

class IAlpha 
{ 
public: 
    virtual ~IAlpha() = 0 {} 
}; 

class IBeta 
{ 
public: 
    virtual ~IBeta() = 0 {} 
}; 

class AbstractClass : public IAlpha, public IBeta 
{ 
public: 
    AbstractClass() 
    { 
    std::wcout << L"AbstractClass::AbstractClass()" << std::endl; 
    } 
    virtual ~AbstractClass() = 0 
    { 
    std::wcout << L"AbstractClass::~AbstractClass()" << std::endl; 
    } 
}; 

class ConcreteClass : public AbstractClass 
{ 
public: 
    ConcreteClass() 
    { 
    std::wcout << L"ConcreteClass::ConcreteClass()" << std::endl; 
    } 
    virtual ~ConcreteClass() 
    { 
    std::wcout << L"ConcreteClass::~ConcreteClass()" << std::endl; 
    } 
}; 

, जब बू

warning C4505: 'AbstractClass::~AbstractClass' : 
unreferenced local function has been removed

अजीब पर्याप्त है, तथापि, उत्पादन अभी भी AbstractClass::~AbstractClass() कहा जाता हो रही है पता चलता है: ilding, मैं निम्न चेतावनी प्राप्त करते हैं।

क्या यह एमएसवीसी 9 (वीएस 2008) में एक बग है? क्या मैं इस चेतावनी को सुरक्षित रूप से अनदेखा कर सकता हूं?

संपादित करें: मैंने क्लास परिभाषा से शुद्ध वर्चुअल विधि परिभाषाओं को अलग करने की कोशिश की है, जैसा स्पष्ट रूप से = 0 {} सिंटैक्स वास्तव में मान्य नहीं है। दुर्भाग्यवश, सी 4505 अभी भी दिखाया गया है, चाहे मैं inline निर्दिष्ट करता हूं या नहीं।

जब से मैं कोई रास्ता नहीं #pragma को यह चेतावनी बाहर सिर्फ इन तरीकों के लिए (चेतावनी कोड के अन्य भागों से ट्रिगर किया जाता है) मिल गया है, मैं AbstractClass से शुद्ध आभासी विनिर्देशक हटाने और कंस्ट्रक्टर बनाने पर भरोसा करने के लिए हो सकता है संरक्षित। एक आदर्श समाधान नहीं है, लेकिन यह एक ग़लत चेतावनी के लिए कक्षा पदानुक्रम के पुनर्मूल्यांकन को धड़कता है।

उत्तर

0

क्या आपने विनाशकों को गैर-इनलाइन तरीके से परिभाषित करने का प्रयास किया था? शायद चेतावनी उससे संबंधित है।

जैसे this code

+0

मैंने आपके लिंक में कोड की कोशिश की; यह वही चेतावनी प्राप्त करता है, भले ही पहले, यह चलने पर सही ढंग से कार्य करता है। – somethingdotjunk

0

कोड संकलित नहीं करना चाहिए। शुद्ध वर्चुअल फ़ंक्शंस को क्लास परिभाषा के अंदर परिभाषित नहीं किया जा सकता है। कक्षाओं के बाहर परिभाषा को ले जाएं:

struct IAlpha { 
    virtual ~IAlpha() = 0; 
}; 
inline IAlpha::~IAlpha() {} 
// similarly for the rest. 

इसके अलावा, कोड सही है और संकलित होना चाहिए।

+0

दिलचस्प; मुझे नहीं पता था कि आप शुद्ध आभासी विनिर्देशक और विधि निकाय को संयोजित नहीं कर सके। दुर्भाग्यवश, मैंने इसे इस तरह से भी आजमाया और चेतावनी अभी भी दिखाई दे रही है (जेफमैगिल से जवाब देखें)। – somethingdotjunk

3

यह एमएसवीसी ++ 2010 और इससे पहले की एक बग है। कोड वास्तव में प्राप्त करता है, भले ही संकलक ने कोड को हटा दिया हो। ऐसा लगता है कि एमएसवीसी ++ 2012 में तय किया गया है। जीसीसी या क्लैंग जैसे अन्य कंपाइलर्स चेतावनी को उत्सर्जित नहीं करते हैं। वाक्यविन्यास "... = 0 {...}" सी ++ 03 मानक खंड 10.4 के अनुसार अवैध है।2 (भले ही MSVC++ शिकायत नहीं करता है) के रूप में यह पहले ही बताया गया है:

नोट: एक समारोह घोषणा दोनों एक शुद्ध-विनिर्देशक और एक परिभाषा प्रदान नहीं कर सकते

हालांकि, एक शुद्ध परिभाषित करने सामान्य रूप में आभासी नाशक अवैध और खंड 12.4.7 राज्यों नहीं है:

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

चेतावनी को अक्षम करने का मेरा तरीका शीर्षक के निम्नलिखित लाइनों को जोड़ने के लिए है:

#if defined(_MSC_VER) && (_MSC_VER <= 1600) 
# pragma warning(disable:4505) 
#endif 

आप तो #pragma warning(push) और #pragma warning(pop) मदद की हो सकता है और अधिक स्थानीय रूप से चेतावनी अक्षम करना चाहते हैं। http://msdn.microsoft.com/en-us/library/2c8f766e(v=vs.80).aspx

चूंकि कोड को कॉल करने के लिए प्रतीत होता है, इसलिए आप मेरी राय में चेतावनियों को अनदेखा कर सकते हैं।

+0

मुझे यह जानने में दिलचस्पी होगी कि यह बग कहां दर्ज किया गया था, इसलिए मैं इसे उद्धृत कर सकता हूं। – chappjc

0

आप वर्चुअल फ़ंक्शन को इनलाइन में परिभाषित नहीं कर सकते हैं।

क्योंकि इनलाइन संकलन में है। आभासी रनटाइम में है।

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