2011-08-26 15 views
6

दृष्टिकोण की जांच करने के लिए बेहतर तरीका है: PermanentEmployee और ContractEmployee: 1जो ऑब्जेक्ट प्रकार

class Employee 
{ 
public: 
    virtual int calculateSalary() = 0; 

}; 

class PermanentEmployee : public Employee { 
    const int salaryPerMonth; 
public: 
    PermanentEmployee(int sal) : salaryPerMonth(sal){} 

    int calculateSalary() { 
     return salaryPerMonth; 
    } 
}; 

class ContractEmployee : public Employee { 
    const int wagesPerHr; 
    int totalHour; 
public: 
    ContractEmployee(int sal) : wagesPerHr(sal), totalHour(0){} 

    void setWorkingDuration(int time) { 
     totalHour = totalHour + time; 
    } 
    int calculateSalary() { 
     return wagesPerHr * totalHour; 
    } 
}; 

class Manager { 
    list<Employee *> ls; 
public: 
    void assignWorkingHour() { 
     list<Employee *>::iterator it; 

     for(it = ls.begin(); it != ls.end(); it++) { 
      Employee *emp = *it; 
      ContractEmployee* contractEmp = dynamic_cast<ContractEmployee* >(emp); 
      if(contractEmp) { 
       contractEmp->setWorkingDuration(5); 
      } 
     } 
    } 
}; 

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

समस्या है: वर्ग कर्मचारी में एक और सदस्य को शामिल

 enum TypeOfEmployee {CONTRACT, PERMANENT}; 
: यहाँ कर्मचारी के प्रकार dynamic_cast ऑपरेटर और प्रबंधक द्वारा निर्धारित किया जा रहा है कर्मचारी की

approach2 प्राप्त वर्ग के सभी प्रकार के बारे में पता करने के लिए है

और कर्मचारी

के प्रकार का निर्धारण करने के लिए TypeOfEmployee की जांच करें कृपया बताएं कि कौन सा बेहतर है या कोई वैकल्पिक दृष्टिकोण है?

+0

प्रश्न की तरह। गतिशील_कास्ट की लागत का उत्सुकता। – Lou

+0

http://www.nerdblog.com/2006/12/how-slow-is-dynamiccast.html आपके लिए प्रासंगिक पढ़ा जा सकता है। –

+0

क्या यह एक होमवर्क प्रश्न है? मैं सिर्फ उत्सुक हूँ। –

उत्तर

7

बेहतर तरीका कोड लिखना है जिसे सटीक ऑब्जेक्ट प्रकार के बारे में ज्ञान की आवश्यकता नहीं है। मुझे लगता है कि इससे निपटने का सबसे शानदार तरीका कर्मचारी वर्ग में setWorkingDuration() को स्थानांतरित करना है। शायद इस तरह:

class Employee 
{ 
public: 
    // Calculates the salary for this employee. 
    // Returns the calculated salary. 
    virtual int calculateSalary() = 0; 
    // Sets the working duration. Does nothing if the employee is permanent. 
    // Returns true if Employee is on a contract, false if permanent. 
    virtual bool setWorkingDuration(int time) 
    { 
     return false; 
    } 
}; 

class PermanentEmployee : public Employee 
{ 
    const int salaryPerMonth; 
public: 
    PermanentEmployee(int sal) : salaryPerMonth(sal) {} 

    int calculateSalary() 
    { 
     return salaryPerMonth; 
    } 
}; 

class ContractEmployee : public Employee 
{ 
    const int wagesPerHr; 
    int totalHour; 
public: 
    ContractEmployee(int sal) : wagesPerHr(sal), totalHour(0) {} 

    int calculateSalary() 
    { 
     return wagesPerHr * totalHour; 
    } 

    bool setWorkingDuration(int time) 
    { 
     totalHour = totalHour + time; 
     return true; 
    } 
}; 

class Manager 
{ 
    list<Employee *> ls; 
public: 
    void assignWorkingHours() 
    { 
     list<Employee *>::iterator it; 
     for(it = ls.begin(); it != ls.end(); it++) 
     { 
      Employee* emp = *it; 
      emp->setWorkingDuration(5); 
     } 
    } 
}; 

इस तरह, Manager वर्ग जानना आवश्यक है कि Employee वास्तव में एक PermanentEmployee या एक ContractEmployee है नहीं है। यही वह है जो बहुरूपता आपको देता है। आमतौर पर अगर आपको dynamic_cast<> का उपयोग करना है, तो आप डिज़ाइन पर एक और नज़र डालना चाहेंगे और देख सकते हैं कि आप इसे छोड़ सकते हैं या नहीं।

+0

मुझे मारो! ख़ूब कहा है। –

+0

आपूर्ति किए गए नमूना उपयोग के संबंध में, मूल्य वापस करने की कोई आवश्यकता नहीं है। व्युत्पन्न कक्षाएं या तो अपने घंटों में वृद्धि करती हैं या कुछ भी नहीं करती हैं। इस मामले में, setWorkingDuration() को शुद्ध आभासी होने की आवश्यकता नहीं है, और केवल उन वर्गों में लागू किया जा सकता है जो घंटों तक काम करते हैं (खाली कक्षा को खाली कार्यान्वयन के साथ छोड़कर)। –

+0

@ जैक स्मिथ: सही। यही कारण है कि मैंने कहा "शायद इस तरह।" :-) यदि 'setWorkingDuration() 'फ़ंक्शन कुछ भी करता है, तो वास्तव में दिलचस्प या आवश्यक नहीं है, तो फ़ंक्शन बस' शून्य 'वापस कर सकता है। –

2

ठीक है, सबटाइप बहुरूपता का पूरा बिंदु कंक्रीट उप-वर्गों को अपने व्यवहार को परिभाषित करने की अनुमति देना है। आप जो कर रहे हैं वह आपके पास मौजूद वस्तु के प्रकार से मेल खाता है, और उसके बाद उस पर निर्भर व्यवहार निर्दिष्ट करता है। अनिवार्य रूप से, आपने उपप्रकारों के पूरे बिंदु को डुप्लिकेट किया है, और इसलिए इसे याद किया है। :)

मेरा सुझाव? इस व्यवहार को Employee पर virtual विधि के रूप में ऑब्जेक्ट पर (इसके प्रबंधक नहीं) को प्रतिनिधि दें।

0

बेशक आप डायनामिक_कास्ट ऑपरेटर के साथ-साथ enum TypeOfEmployee भी कर सकते हैं लेकिन आखिरी में पॉलिमॉर्फिज्म के साथ कुछ भी सामान्य नहीं है।

आपको सोचना चाहिए कि क्यों प्रबंधक स्थायी कर्मचारी को कामकाजी घंटे सेट करता है। ठीक है न? एक और तरीका बेस वर्क इंटरफेस का विस्तार करना है वर्कवर्किंग वर्चुअल विधि के साथ कर्मचारी। फिर स्थायी कर्मचारी में यह कुछ भी नहीं करेगा।

0

अन्य लोगों ने ठेठ मामलों के लिए पहले से ही उत्तर (स्वीकृति के लायक) प्रदान कर लिया है।

आप अपने द्विआधारी आकार (निर्यात प्रतीकों की संख्या), निष्पादन समय, गतिशील आवंटन, कुल स्मृति के उपयोग की गिनती, और मौका क्रम त्रुटियों के लिए करता है, तो आप कर सकते हैं कम कर सकते हैं:

यहाँ कम ठेठ मामलों के लिए कुछ नोट कर रहे हैं रनटाइम पर गतिशील प्रकारों का उपयोग करने से बचें।

वर्चुअल और रनटाइम पॉलीमोर्फिज्म को हटाने से आकार 75% से अधिक हो सकता है।

इसी तरह, आप सरल मामलों में प्रकार या कार्यान्वयन की पहचान करने के लिए चर का उपयोग कर सकते हैं (जैसे आपका दृष्टिकोण 2)।

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

प्रभावी रूप से वर्चुअल विधियों और रनटाइम पॉलीमोर्फिज्म को फ़ंक्शन पॉइंटर्स के साथ बदलकर इसे 130K तक लाता है। यह अभी भी 360 कक्षाएं है।

चर के साथ एक वर्ग में कार्यान्वयन को समेकित करने के लिए केवल डाइलिब का आकार केवल 10K तक लाया गया।

फिर से, यह दृष्टिकोण द्विआधारी आकार से कहीं अधिक प्रभावित करता है।

मेरा मुद्दा यह है कि यह सही परिस्थितियों में एक अच्छा प्रतिस्थापन है।

0

दृष्टिकोण तीन: अलग-अलग ठेकेदारों का ट्रैक रखें।

class Manager { 
    typedef list<Employee*> Employees; // Contains all employees, including contractors. 
    typedef list<ContractEmployee*> Contractors; // Contractors are in this list as well. 
    Employees employees; 
    Contractors contractors; 
public: 
    void assignWorkingHour() { 
     for(Contractors::iterator it = contractors.begin(); it != contractors.end(); ++it) { 
      (*it)->setWorkingDuration(5); 
     } 
    } 

    int calculateEmployeeCost() { 
     int totalSalary = 0; 
     for (Employees::const_iterator it = employees.begin(); it != employees.end(); ++it) { 
      totalSalary += (*it)->calculateSalary(); 
     } 
     return totalSalary; 
    } 
}; 
संबंधित मुद्दे