0

I have a vector of base pointer and need to know which derive class of this base class for example

class Document {
protected :
string name;
Date date_borrow; // Date is class
};

class Book : public Document {
private :
int book_pages;
};

class Reference : public Document {
private :
string writer;
};

class Member {
   protected :
        vector < Document* > document;

};
class Library {
public :
void borrow ( Member* member, Document* document ){
   member->add_document ( document );
}
private : 
vector < Document* > documents;
vector < Member* > members;

};

in this code when member borrow document , i need to know the document* is a book or reference to calculate penalty for late. (the function of penalty is different for book and reference) and then push_back document in documents in private of member. how can i find the type of derive?

Barry
  • 286,269
  • 29
  • 621
  • 977
AAAK
  • 1

3 Answers3

2

Sounds like a job for Polymorphism:

class Document {
public:
    virtual ~Document() { }
    virtual double latePenalty() = 0; 
};


class Book : public Document {
public:
    double latePenalty() { 
        // book-specific late penalty
        return 5.0 * daysLate() + 17.0; 
    }
};

class Reference: public Document {
public:
    double latePenalty() { 
        // reference-specific late penalty
        return 1e6; // because that'll teach you! 
    }
};

vector < Document* > documents;

This way, calling latePenalty() will, via dynamic dispatch, call the correct version for each type of Document.

Barry
  • 286,269
  • 29
  • 621
  • 977
  • This solution is better if you want the late-penalty functionality to be handled by the objects instead of the library objects. – caps Nov 20 '14 at 22:26
  • thanks for your answer , but two question ( I'm beginner in programming) : 1- what is in line 3? 2-when member borrow document ,the document push_back in vector < Document* > documents and the date of document is set . but if the library have 3 of this book(the quantity of book is in private) all of the book timed borrow change,and it's wrong,and it's happend because i push_back the pointer that point to library document and if i try to build new pointer i need the type of the document. – AAAK Nov 21 '14 at 10:40
  • @AAAK [When to use virtual destructors](http://stackoverflow.com/questions/461203/when-to-use-virtual-destructors) – Barry Nov 21 '14 at 11:49
  • And I don't understand your second question. – Barry Nov 21 '14 at 11:50
0

Technically you can just put a virtual destructor in the topmost base class, then use dynamic_cast to attempt to downcast pointers.

Instead I strongly advice you to put the relevant virtual functions in the pointee class.

Virtual functions are a way to do type-safe, efficient down-casting. Manual down-casting via e.g. dynamic_cast is inefficient and error-prone.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
-2

What I do in these situations is use an enum.

enum document_type { dtBook, dtReference };

Then each class would have a member like this:

class Document {
protected:
    std::string name;
    Date date_borrow; // Date is a class
public:
    virtual document_type GetType() = 0;
    // note that this makes the class pure virtual. If that is undesirable,
    // you might want to add a third type to the enum, like dtDocument, as
    // a default return value
};

class Book : public Document {
    document_type GetType() {
        return dtBook;
    };

private:
    int book_pages;
};

class Reference : public Document {
    document_type GetType() {
        return dtReference;
    };

private:
    std::string writer;
};
sehe
  • 374,641
  • 47
  • 450
  • 633
caps
  • 1,225
  • 14
  • 24
  • **-1** Well known anti-pattern. – Cheers and hth. - Alf Nov 20 '14 at 22:26
  • Whenever you derive a new class, you have to remember to update the get type. If I derive from Book, should I return dtBook or my own enum? If the file with enum is locked, how can I add a new id? – Neil Kirk Nov 20 '14 at 22:28
  • 1
    @caps: E.g. google it? Or *Object Oriented Software Construction* by Betrand Meyer. He left out enumeration types in the Eiffel language just to help people avoid this anti-pattern. – Cheers and hth. - Alf Nov 20 '14 at 22:28
  • Yup. That's the code treatment that teaches people. Adding your "stuff" to already high entropy mass of code... (Note how others didn't have this problem) – sehe Nov 20 '14 at 23:54