2011-03-07 14 views
8

क्या कोई सार तत्व घोषित किए बिना सी ++ में कक्षा सार बनाना संभव है? वर्तमान में, मेरे पास स्टेटसाइट स्प्रिट और डायनामिकस्प्रिट सबक्लास के साथ एक स्प्राइट क्लास है। मैं स्प्राइट क्लास सार बनाना चाहता हूं।सार तत्वों के बिना सार वर्ग

समस्या यह है कि वे साझा करने के कोई भी तरीके नहीं हैं। खैर, दोनों StaticSprite और DynamicSprite ड्रॉ() - विधि साझा कर सकते हैं, लेकिन इस विधि के पैरामीटर अलग हैं इसलिए यह एक विकल्प नहीं है।

धन्यवाद!

संपादित करें:

स्प्राइट:

class Sprite 
{ 
    public: 
     Sprite(HINSTANCE hAppInst, int imageID, int maskID); 
     ~Sprite(); 

    protected: 
     HINSTANCE hAppInst; 
     HBITMAP hImage; 
     HBITMAP hMask; 
     BITMAP imageBM; 
     BITMAP maskBM; 
     HDC hSpriteDC; 
}; 

Staticsprite:

class StaticSprite : public Sprite 
{ 
    public: 
     StaticSprite(HINSTANCE hAppInst, int imageID, int maskID); 
     ~StaticSprite(); 

     void draw(Position* pos, HDC hBackbufferDC); 
}; 

Dynamicsprite:

class DynamicSprite : public Sprite 
{ 
    public: 
     DynamicSprite(HINSTANCE hAppInst, int imageID, int maskID); 
     ~DynamicSprite(); 

     void draw(HDC hBackbufferDC); 
}; 
यहाँ मैं क्या करने की कोशिश कर रहा हूँ प्रदर्शित करने के लिए कोड है

जैसा कि आप देखते हैं, स्प्राइट-ऑब्जेक्ट बनाने के लिए बेकार है, इसलिए मैं उस वर्ग सार को बनाना चाहता हूं। लेकिन मैं draw() सार नहीं बना सकता क्योंकि यह विभिन्न मानकों का उपयोग करता है।

+2

यह सार तत्वों के बिना सार क्यों होना चाहिए? –

+1

शायद वे इसे तत्काल नहीं चाहते हैं – Erix

+1

बेस क्लास होने का कोई मतलब नहीं है, वैसे भी विरासत प्राप्त करने के लिए कोई तरीका नहीं है? – Rob

उत्तर

15

आप अपने नाशक के रूप में शुद्ध आभासी घोषणा कर सकते हैं, सभी वर्गों के बाद से एक ले लो।

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

हालांकि, आपको इस विनाशक को कहीं और परिभाषित करने की आवश्यकता होगी।

AbstractClass::~AbstractClass() {} 
+0

समस्या यह है कि कक्षा में कुछ सदस्य हैं जिन्हें विनाशक में हटा दिया जाना चाहिए, इसलिए इसे सार बनाने से मेमोरी लीक हो जाएगी ... – Bv202

+0

चूंकि बेस क्लास विनाशक आभासी है, इसलिए आपके व्युत्पन्न वर्ग विनाशक के लिए विनाशक को कब और कहाँ आवश्यकता होगी कहा जाएगा। कोई समस्या नहीं होनी चाहिए। –

+2

@ बीवी 202 - आप विनाशक का कार्यान्वयन भी प्रदान करते हैं, ताकि आप वहां सफाई कर सकें। – fizzer

2

कोई नहीं है।

आप निश्चित रूप से इस इस्तेमाल कर सकते हैं:

class Sprite 
{ 
}; 

लेकिन निश्चित रूप से संकलक जब आप इसे का एक उदाहरण बनाने की कोशिश में शिकायत करने नहीं जा रहा है।

आप एक शुद्ध आभासी नाशक जोड़ सकते हैं:

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

या आप निर्माता की रक्षा कर सकते हैं, इन्स्टेन्शियशन रोक:

class Sprite 
{ 
protected: 
    Sprite(); 
}; 
0

एक विशुद्ध रूप से अमूर्त वर्ग है कि यह से पाने के बिना instantiated नहीं किया जा सकता है बनाने के लिए - आप कम से कम एक सार विधि परिभाषित करना होगा।

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

virtual void blah() const = 0; 

नहीं तो आप, एक अमूर्त वर्ग

+0

आखिरकार, सवाल "परेशान क्यों है"? – Randolpho

+0

@Randolpho - सवाल बदल गया। क्या आपका मतलब है कि एक अमूर्त वर्ग क्यों है, या यदि इसका कोई तरीका नहीं है तो इसे सार क्यों बनाएं? –

+0

हाँ, सवाल बदल गया। ऐसा होता है तो मुझे बहुत बुरा लगता है। :) – Randolpho

2

ऐसा करने के पारंपरिक तरीके से एक शुद्ध आभासी नाशक बनाने के लिए है के रूप में किसी भी वर्ग का उपयोग कर सकते तो इसे लागू।

// .h 
struct Foo { 
    virtual ~Foo() = 0; 
}; 

// .cpp 
Foo::~Foo() { 
} 
+1

आप एक शुद्ध आभासी लागू नहीं कर सकते हैं। – Cthutu

+5

@Cthutu वास्तव में आप * शुद्ध आभासी तरीकों को लागू कर सकते हैं। इसका मतलब है कि बच्चे को इसे फिर से लागू करना है। –

+2

और विनाशक मामले में, आपको अवश्य ही चाहिए। – fizzer

11

वर्ग कुछ नहीं करता है और कुछ भी नहीं प्रदान करता है, और केवल एक मार्कर के रूप में मौजूद है, वहाँ है या नहीं, यह सार है के बारे में चिंता करने के लिए कोई कारण नहीं है। यह अनिवार्य रूप से एक गैर-मुद्दा है।

यदि आप पूरी तरह से यह सुनिश्चित करना चाहते हैं कि विरासत के संदर्भ में किसी को भी तत्काल नहीं किया गया है, तो protected constructors का उपयोग करें।

कृपया शुद्ध वर्चुअल विनाशक बनाने से बचें। इस तरह पागलपन झूठ बोलता है।

2

समस्या यह है कि कोई भी वे साझा नहीं करते हैं।

वैसे आपकी समस्या ठीक है। आपको यहां विरासत का उपयोग नहीं करना चाहिए! यदि आप एक वर्ग के लिए एक वर्ग को प्रतिस्थापित करने का इरादा नहीं रखते हैं तो वे माता-पिता के संबंध में नहीं होना चाहिए।

जरूरतों के आधार पर उन्हें पूरी तरह से असंबंधित, टेम्पलेट्स या उपयोग संरचना होना चाहिए।

संपादित करें: कोड नमूना के आधार पर, आप पुन: उपयोग करने के लिए विरासत में हैं और मैं इसके बजाय संरचना का उपयोग करने का सुझाव दूंगा। Spritestruct हो सकता है जिसका स्वामित्व DynamicSprite और StaticSprite दोनों के स्वामित्व में है। आप जितना उचित हो उतना/छोटा सहायक तर्क Sprite डाल सकते हैं।

+0

मैंने अपनी पहली पोस्ट में कोड जोड़ा है। आपको इसे कैसे हल करना चाहिए? – Bv202

+0

-1 क्योंकि आप संभवतः नहीं जानते कि विरासत का उपयोग किया जाना चाहिए या नहीं। अपने बयान में एक उत्कृष्ट काउंटर पॉइंट के लिए अलेक्जेंड्रेस्कू के विज़िटर फ्रेमवर्क की समीक्षा करें। –

3

अपनी पोस्ट की विशिष्ट परिस्थितियों के लिए, निजी विरासत पर विचार करें। इस तरह आप दुनिया के लिए एक नकली आईएस-ए संबंधों के विज्ञापन के बिना आधार के कार्यान्वयन का आलस्य उपयोग कर सकते हैं।

-1

तुम सच में विरासत उपयोग करना आवश्यक है, गैर आभासी इंटरफेस (NVI) मुहावरा का उपयोग कर (http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.3 देखें)

अनिवार्य रूप से आधार वर्ग एक ओवरलोड, तरीकों में से गैर आभासी सेट है, जो शुद्ध संरक्षित कॉल परिभाषित करेगा पर विचार व्युत्पन्न कक्षाओं से वर्चुअल फ़ंक्शन।

जो आप निश्चित रूप से करना नहीं चाहते हैं वह वर्चुअल फ़ंक्शन ओवरलोड करें (जो ऐसा लगता है कि आप वास्तव में करना चाहते हैं)।

1

सबसे अच्छा तरीका वर्ग कंस्ट्रक्टर्स, इस तरह से वर्ग सीधे instantiated नहीं किया जा सकता है की रक्षा के लिए है और इसलिए यह अनिवार्य रूप से सार है:

class SomeBaseClass 
{ 
protected: 
    SomeBaseClass() {} 
    SomeBaseClass(const SomeBaseClass &) {} 
    SomeBaseClass &operator=(const SomeBaseClass&) {} 
public: 
    virtual ~SomeBaseClass() {} 
    ... 
}; 

या, नए शैली:

class SomeBaseClass 
{ 
protected: 
    SomeBaseClass() = default; 
    SomeBaseClass(const SomeBaseClass &) = delete; 
    SomeBaseClass &operator=(const SomeBaseClass&) = delete; 
public: 
    virtual ~SomeBaseClass() = default; 
    ... 
}; 

नाशक आम तौर पर है सार्वजनिक रखने के लिए बेहतर है क्योंकि आप किसी ऑब्जेक्ट को अपने बेस क्लास पॉइंटर से हटाना चाहते हैं।

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