#include #include #include #include #include #include using namespace std; using namespace boost; class Employee { public: Employee(uint64_t id, string name); void print() const; // Should be virtual uint64_t getId(); const string &getName(); // should be const virtual const string getTitle(); // should be const uint64_t getSalary(); void setSalary(uint64_t s); private: uint64_t id_; const string name_; uint64_t salary_; } /* * The above missing ; yields the following error: * bad_db.cpp:10: error: new types may not be defined in a return type * bad_db.cpp:10: note: (perhaps a semicolon is missing after the definition of "Employee") * bad_db.cpp:30: error: return type specification for constructor invalid */ Employee::Employee(uint64_t id, string name) : id_(id), name_(name), salary_(0) { } void Employee::print() const { cout << getTitle() << ":" << endl; cout << " " << name_ << endl; } uint64_t Employee::getId() { return id_; } const string &Employee::getName() { return name_; } const string Employee::getTitle() { return "Basic Employee"; } uint64_t Employee::getSalary() { return salary_; } /* This setSalary definition generates the following error, because we forgot to prefix it with * Employee:: * bad_db_tmp.cpp: In function "void setSalary(uint64_t)": * bad_db_tmp.cpp:46: error: "salary_" was not declared in this scope */ void setSalary(uint64_t s) { salary_ = s; } class Manager : public Employee { public: Manager(uint64_t id, string name); virtual void print() const; void add_report(shared_ptr emp); virtual const string getTitle(); protected: list > direct_reports_; }; Manager::Manager(uint64_t id, string name) : Employee(id, name) {} void Manager::print() const { cout << getTitle() << ":" << endl; cout << "\t" << getName() << endl; cout << "\t" << "Supervises:" << endl; if (direct_reports_.empty()) { cout << "\t\tNobody" << endl; } else { /* This use of a non-const iterator in a const iterator in a const method generates the * following mysterious error, because the compiler doesn't know begin() won't modify the list: * bad_db_tmp.cpp: In member function "virtual void Manager::print() const": * bad_db_tmp.cpp:74: error: no match for "operator=" in "it = ((const Manager*)this)->Manager::direct_reports_.std::list<_Tp, _Alloc>::begin [with _Tp = boost::shared_ptr, _Alloc = std::allocator >]()" * /usr/lib/gcc/i686-redhat-linux/4.4.5/../../../../include/c++/4.4.5/bits/stl_list.h:114: note: candidates are: std::_List_iterator >& std::_List_iterator >::operator=(const std::_List_iterator >&) */ list >::iterator it; for(it = direct_reports_.begin(); it != direct_reports_.end(); it++) { cout << "\t\t\t" << (*it)->getTitle() << " " << (*it)->getName() << endl; } } } const string Manager::getTitle() { return "Manager"; } void Manager::add_report(shared_ptr e) { direct_reports_.push_back(e); } class President : public Manager { public: President(uint64_t id, string name); virtual void print() const;// We declare but do not define this virtual method, so we get a linker error about "undefined reference to `vtable for President'" virtual const string getTitle(); }; President::President(uint64_t id, string name) : Manager(id, name) {} const string President::getTitle() { return "President"; } class Developer : public Employee { public: Developer(uint64_t id, string name); virtual void print() const; virtual const string getTitle(); }; Developer::Developer(uint64_t id, string name) : Employee(id, name) {} void Developer::print() const { cout << getTitle() << ":" << endl; cout << "\t" << getName() << endl; } const string Developer::getTitle() { return "Developer"; } struct lt_employee { bool operator()(const shared_ptr &e1, const shared_ptr &e2) { return e1->getId() < e2->getId(); } }; struct lt_uint64 { bool operator()(const uint64_t &a, const uint64_t &b) { return a < b; } }; int main(int argc, char** argv) { map,lt_employee> db; map,lt_uint64>::iterator it; Manager *hank = new President(0,"Hank"); /* Because the map contains shared pointers to const Employees, but we assign an Employee*, we * see an error message like this: * bad_db_tmp.cpp: In function "int main(int, char**)": * bad_db_tmp.cpp:129: error: no match for "operator=" in "db.std::map<_Key, _Tp, _Compare, _Alloc>::operator[] [with _Key = long long unsigned int, _Tp = boost::shared_ptr, _Compare = lt_employee, _Alloc = std::allocator > >](((const long long unsigned int&)((const long long unsigned int*)(&0ull)))) = hank" * /usr/include/boost/smart_ptr/shared_ptr.hpp:303: note: candidates are: boost::shared_ptr< >& boost::shared_ptr< >::operator=(const boost::shared_ptr< >&) [with T = const Employee] * * The error basically tells us that there is no operator= definition for the result of the * db[0] lookup (which is a newly-allocated shared pointer to null since we're inserting a new * value, hence the &0ull) that takes the same type as the variable 'hank'. All it can find is * an operator= that takes a shared_ptr (this implies hank has the wrong type). * We see similar errors on other lines. */ db[0] = hank; /* We also see another error on the line above, because we're (implicitly, by inserting for a * new key) instantiating a new shared_ptr using a comparator that operates on * the map's values, instead of the map's keys; db should also use lt_uint64 as a comparator. */ Manager *steve = new Manager(1,"Steve"); // we should make this a shared_ptr; making it shared_ptr would break when we add steve as hank's report, since add_report takes a non-const Employee db[1] = steve; hank->add_report(steve); Employee *colin = new Developer(2,"Colin"); steve->add_report(colin); db[2] = colin; Employee *aryan = new Developer(3,"Aryan"); steve->add_report(aryan); db[3] = aryan; for(it = db.begin(); it != db.end(); it++) { (*it).second->print(); (*it).second->setSalary(100000); // since we're iterating over const Employees, we can't call setSalary(). } return 0; }