2017-01-14 9 views
5

से विरासत मान लीजिए मैं निम्नलिखित वर्ग परिभाषाओंसशर्त शुद्ध आधार वर्ग

है
struct base { 
    virtual int f() = 0; 
}; 

struct A: public base { 
    int f() final { return 1; } 
}; 

struct B: public base { 
    int f() final { return 2; } 
}; 

यह टेम्पलेट्स है कि एक bool पैरामीटर निर्दिष्ट करता है कि base या नहीं से विरासत के लिए कि क्या ले में A और B चालू करने के लिए संभव है? मेरे पास ऐसे मामले हैं जो एक सामान्य इंटरफ़ेस प्रदान करने वाले बेस क्लास की आवश्यकता नहीं करते हैं या नहीं।

मान लें कि A और B में बहुत से सदस्य कार्य हैं, इसलिए डुप्लीकेटिंग कार्यान्वयन कठिन होगा। लेकिन sizeof(A) और sizeof(B) छोटे हैं।

+0

क्या आपको दो संस्करणों की आवश्यकता है? मान लीजिए कि 'बेस' में केवल अमूर्त कार्य होते हैं, वहां कोई रनटाइम लागत नहीं होनी चाहिए। आपके उदाहरण में आपके ऑप्टिमाइज़र को यह देखना चाहिए कि कोई भी 'ए' वहां से 'f() 'का उपयोग करने जा रहा है क्योंकि यह' अंतिम 'है। – Guvante

+0

@ गुवाँटे: यह प्रकार पॉलीमोर्फिक बनाता है, जो इसे एक vtable देता है। रनटाइम लागत नहीं, लेकिन फिर भी एक लागत। – ildjarn

+0

@ गुवाएं विरासत प्रकार का आकार एक सूचक के आकार से बड़ा होता है, जो vtable को इंगित करता है। – SU3

उत्तर

3

मैं कोड डुप्लिकेशंस के बिना, अधिक प्रत्यक्ष दृष्टिकोण के साथ आया था।

struct base { 
    virtual int f() = 0; 
}; 

struct empty_base { }; 

template <bool Inherit> 
struct A final: public std::conditional_t<Inherit,base,empty_base> { 
    int f() { return 1; } 
}; 
4

ज़रूर:

template <bool> struct A 
{ 
    // ... 
}; 

template <> struct A<true> : base 
{ 
    // ... 
}; 

(ध्यान दें कि आप बना सकते हैं कि A<true>A<false> से निकाले जाते हैं कि अगर अतिरेक से बचा जाता है।)

उदाहरण के लिए:

template <bool> struct A 
{ 
    void f() { std::cout << "A::f called\n"; } 
}; 

template <> struct A<true> : A<false>, base 
{ 
    void f() override { A<false>::f(); } 
}; 

int main() 
{ 
    A<false> a1; 
    A<true> a2; 
    a1.f(); 
    a2.f(); 
    static_cast<base&>(a2).f(); 
} 
+0

हालांकि मैं यह 'ए ए के लिए अनुमति नहीं दूंगा; आधार * पी = और ए; पी-> एफ(); 'ठीक से काम करने के लिए। मुझे लगता है कि केवल तभी होगा जब आधार :: एफ() 'सार नहीं था (हीरा समस्या)। क्या आपका कार्यान्वयन मेरे मूल कार्यान्वयन की तुलना में 'p-> f()' किसी भी धीमी गति से कॉल करता है? – SU3

+0

यदि ' :: f()' final' बनाने का कोई तरीका है? – SU3

+1

आपको घोषणा की प्रतिलिपि बनाना होगा (और दूसरे को 'ए :: f() 'के माध्यम से कॉल करना होगा)। इसके अलावा यदि आप 'ए ' में 'f()' डालते हैं, तो यह 'आधार :: एफ() 'को अमूर्त आवश्यकता के रूप में पूरा नहीं करेगा। – Guvante

1

आप एक शुद्ध आधार का उपयोग कर रहे के बाद से क्लास भेद महत्वपूर्ण नहीं होना चाहिए क्योंकि जब आप A::f() पर कॉल करते हैं तो आपके ऑप्टिमाइज़र वर्चुअल फ़ंक्शन कॉल से बचेंगे क्योंकि वाई कभी भी व्युत्पन्न कक्षा नहीं होगी जो f() के एक अलग संस्करण को लागू करेगी।

यदि आप प्रत्येक कार्य में final जोड़ने से बचने के लिए A से विरासत में रहने की योजना नहीं बनाते हैं तो आप class A final : base भी कर सकते हैं।

+0

धन्यवाद। मैं भूल गया कि आप कार्यों के बजाय कक्षा पर 'अंतिम' छड़ी कर सकते हैं। – SU3

+0

आप 'कक्षा ए मुहरबंद भी कर सकते हैं: सार्वजनिक आधार {...}; ' –

+0

' मुहरबंद 'क्या है? क्या यह एक माइक्रोसॉफ्ट एक्सटेंशन है? – SU3

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