2010-03-05 23 views
6

पर विचार करें निम्नलिखित कोड अधिभावी:अपवाद विनिर्देश जब एक आभासी समारोह


class A 
{ 
public: 
    virtual void f() throw (int) { } 
}; 

class B: public A 
{ 
public: 
    void f() throw (int, double) { } 
}; 

जब संकलित है, यह कहना है व्युत्पन्न वर्ग बी ए क्या इस का महत्व है की तुलना में एक हारने फेंक विनिर्देशन होता है कि? यदि हम उनके अपवाद विनिर्देश का आदान-प्रदान करने का प्रयास करते हैं, जैसे कि ए :: एफ() int और double फेंकता है जबकि बी :: एफ() केवल int को फेंकता है, तो त्रुटि प्रकट नहीं होती है।

+2

मैं ईमानदारी से आशा करता हूं कि आप कभी भी उन वर्गों के उदाहरण नहीं फेंकें जो अपवाद के रूप में उपयोग नहीं किए जाने वाले हैं और यह केवल आपके प्रश्न के त्वरित और गंदे चित्रण के लिए है :) –

+0

Matthieu: आह, हां। मै समझता हुँ। – jasonline

उत्तर

13
  1. Don't use exception specifications in C++. जावा के मुकाबले यह बहुत प्रतिद्वंद्वी है।
  2. व्युत्पन्न वर्ग में व्यापक विनिर्देश होने से एलएसपी (लिस्कोव प्रतिस्थापन सिद्धांत) टूट जाता है।

बिंदु 2 पर विस्तार करने के लिए: A की कॉल उम्मीद करते हैं कि केवल int बाहर आता है, लेकिन अगर आप का प्रयोग कर एक B (जो है, क्योंकि यह सार्वजनिक रूप से A से ली गई है, यह भी मतलब है कि यह एक A के रूप में प्रयोग करने योग्य है), अचानक double बाहर भी आ सकता है, और यह A के अनुबंध को तोड़ देगा (केवल int फेंक दिया जाता है)।

+1

इस पर हर्ब सटर के लिए (जो क्रिस के साथ सहमत हैं) के लिए देखें, http://www.gotw.ca/publications/mill22.htm –

+1

वास्तव में, सी ++ इसके लिए निहित कार्य घोषणाओं में भी इसके लिए जांच करता है (कार्यों के लिए यह सीधे कॉल करता है उन, उनके अपवाद spec में बुलाया समारोह की चश्मे शामिल हैं): 'संरचना ए {आभासी ~ ए() फेंक(); }; संरचना बी {~ बी() फेंक (int); }; संरचना सी: ए, बी {};/* त्रुटि: ~ सी() फेंक दिया है (int), लेकिन ~ ए() फेंक दिया है()! */' –

+0

@ नील: लिंक के लिए धन्यवाद; मैंने इसका उपयोग करने के लिए अपना लिंक (मूल रूप से एक गॉटव एक) बदल दिया है। :-) –

1

आपका बी Liskov प्रतिस्थापन सिद्धांत का उल्लंघन करता है - उदाहरण के लिए:

 
void foo(A* a) throw() // ie I will not throw 
{ 
    try 
    { 
    a->f(); 
    } 
    catch(int) 
    {} 
} 

यह एक के लिए इंटरफेस के अनुसार वैध है; विशेष रूप से, हम एक डबल को फेंकने की उम्मीद नहीं करते हैं। लेकिन पर विचार अगर हम इंटरफेस आप का वर्णन के साथ

foo(new B)

कॉल करने के लिए थे, और

B::f()
एक डबल फेंक रहे थे।

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