Employees and Organizational Hierarchy

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
5
down vote

favorite
1












Employee hierarchy in an Organization is classic example of modeling Composite design pattern. Following are the details that are to be modeled:



  1. There are two type of employees; Manager, and Developer.

  2. A Manager manages a team that can comprise managers, and developer.

  3. A Developer has fixed salary at given point of time and get work from the manager.

  4. The salary of a manager is the sum of salary of all the team members + 10K.

  5. We need to model work distribution, and salary of employees of the organization.

 



#include <string>
#include <vector>
#include <iostream>

using namespace std;

class Employee
private:
string _name;
public:
Employee(string name_)
_name = name_;

string name()
return _name;

void virtual work() = 0;
float virtual salary() = 0;
;
// Common Interface to interact with Manager, and Developer
class Developer : public Employee
private:
float _salary;
public:
Developer(string name_,float salary_) : Employee(name_),_salary(salary_)
void work()
cout << "Developer " << name() << " Workedn";
// A developer works own.

float salary()
return _salary;

;

class Manager : public Employee
private:
vector<Employee*> _team;
public:
Manager(string name_) : Employee(name_)
void add(Employee * emp_)
_team.push_back(emp_);

void work()
cout << "Manager " << name() << " Distributed Workn";
for(vector<Employee*>::iterator it = _team.begin(); it!=_team.end(); ++it)
(*it)->work();

// A manager distributes work in team members.

float salary()
float salary_ = 0.0;
for(vector<Employee*>::iterator it = _team.begin(); it!=_team.end(); ++it)
salary_ += (*it)->salary()+15000;

return salary_;
// Salary of a manager is derived from team members.

;
int main()
Developer d1("developer1",10000);
Developer d2("developer2",15000);
Manager m1("manager1");
m1.add(&d1);
m1.add(&d2);
Manager m2("manager2");
m2.add(&m1);
m2.work();
return 0;







share|improve this question



























    up vote
    5
    down vote

    favorite
    1












    Employee hierarchy in an Organization is classic example of modeling Composite design pattern. Following are the details that are to be modeled:



    1. There are two type of employees; Manager, and Developer.

    2. A Manager manages a team that can comprise managers, and developer.

    3. A Developer has fixed salary at given point of time and get work from the manager.

    4. The salary of a manager is the sum of salary of all the team members + 10K.

    5. We need to model work distribution, and salary of employees of the organization.

     



    #include <string>
    #include <vector>
    #include <iostream>

    using namespace std;

    class Employee
    private:
    string _name;
    public:
    Employee(string name_)
    _name = name_;

    string name()
    return _name;

    void virtual work() = 0;
    float virtual salary() = 0;
    ;
    // Common Interface to interact with Manager, and Developer
    class Developer : public Employee
    private:
    float _salary;
    public:
    Developer(string name_,float salary_) : Employee(name_),_salary(salary_)
    void work()
    cout << "Developer " << name() << " Workedn";
    // A developer works own.

    float salary()
    return _salary;

    ;

    class Manager : public Employee
    private:
    vector<Employee*> _team;
    public:
    Manager(string name_) : Employee(name_)
    void add(Employee * emp_)
    _team.push_back(emp_);

    void work()
    cout << "Manager " << name() << " Distributed Workn";
    for(vector<Employee*>::iterator it = _team.begin(); it!=_team.end(); ++it)
    (*it)->work();

    // A manager distributes work in team members.

    float salary()
    float salary_ = 0.0;
    for(vector<Employee*>::iterator it = _team.begin(); it!=_team.end(); ++it)
    salary_ += (*it)->salary()+15000;

    return salary_;
    // Salary of a manager is derived from team members.

    ;
    int main()
    Developer d1("developer1",10000);
    Developer d2("developer2",15000);
    Manager m1("manager1");
    m1.add(&d1);
    m1.add(&d2);
    Manager m2("manager2");
    m2.add(&m1);
    m2.work();
    return 0;







    share|improve this question























      up vote
      5
      down vote

      favorite
      1









      up vote
      5
      down vote

      favorite
      1






      1





      Employee hierarchy in an Organization is classic example of modeling Composite design pattern. Following are the details that are to be modeled:



      1. There are two type of employees; Manager, and Developer.

      2. A Manager manages a team that can comprise managers, and developer.

      3. A Developer has fixed salary at given point of time and get work from the manager.

      4. The salary of a manager is the sum of salary of all the team members + 10K.

      5. We need to model work distribution, and salary of employees of the organization.

       



      #include <string>
      #include <vector>
      #include <iostream>

      using namespace std;

      class Employee
      private:
      string _name;
      public:
      Employee(string name_)
      _name = name_;

      string name()
      return _name;

      void virtual work() = 0;
      float virtual salary() = 0;
      ;
      // Common Interface to interact with Manager, and Developer
      class Developer : public Employee
      private:
      float _salary;
      public:
      Developer(string name_,float salary_) : Employee(name_),_salary(salary_)
      void work()
      cout << "Developer " << name() << " Workedn";
      // A developer works own.

      float salary()
      return _salary;

      ;

      class Manager : public Employee
      private:
      vector<Employee*> _team;
      public:
      Manager(string name_) : Employee(name_)
      void add(Employee * emp_)
      _team.push_back(emp_);

      void work()
      cout << "Manager " << name() << " Distributed Workn";
      for(vector<Employee*>::iterator it = _team.begin(); it!=_team.end(); ++it)
      (*it)->work();

      // A manager distributes work in team members.

      float salary()
      float salary_ = 0.0;
      for(vector<Employee*>::iterator it = _team.begin(); it!=_team.end(); ++it)
      salary_ += (*it)->salary()+15000;

      return salary_;
      // Salary of a manager is derived from team members.

      ;
      int main()
      Developer d1("developer1",10000);
      Developer d2("developer2",15000);
      Manager m1("manager1");
      m1.add(&d1);
      m1.add(&d2);
      Manager m2("manager2");
      m2.add(&m1);
      m2.work();
      return 0;







      share|improve this question













      Employee hierarchy in an Organization is classic example of modeling Composite design pattern. Following are the details that are to be modeled:



      1. There are two type of employees; Manager, and Developer.

      2. A Manager manages a team that can comprise managers, and developer.

      3. A Developer has fixed salary at given point of time and get work from the manager.

      4. The salary of a manager is the sum of salary of all the team members + 10K.

      5. We need to model work distribution, and salary of employees of the organization.

       



      #include <string>
      #include <vector>
      #include <iostream>

      using namespace std;

      class Employee
      private:
      string _name;
      public:
      Employee(string name_)
      _name = name_;

      string name()
      return _name;

      void virtual work() = 0;
      float virtual salary() = 0;
      ;
      // Common Interface to interact with Manager, and Developer
      class Developer : public Employee
      private:
      float _salary;
      public:
      Developer(string name_,float salary_) : Employee(name_),_salary(salary_)
      void work()
      cout << "Developer " << name() << " Workedn";
      // A developer works own.

      float salary()
      return _salary;

      ;

      class Manager : public Employee
      private:
      vector<Employee*> _team;
      public:
      Manager(string name_) : Employee(name_)
      void add(Employee * emp_)
      _team.push_back(emp_);

      void work()
      cout << "Manager " << name() << " Distributed Workn";
      for(vector<Employee*>::iterator it = _team.begin(); it!=_team.end(); ++it)
      (*it)->work();

      // A manager distributes work in team members.

      float salary()
      float salary_ = 0.0;
      for(vector<Employee*>::iterator it = _team.begin(); it!=_team.end(); ++it)
      salary_ += (*it)->salary()+15000;

      return salary_;
      // Salary of a manager is derived from team members.

      ;
      int main()
      Developer d1("developer1",10000);
      Developer d2("developer2",15000);
      Manager m1("manager1");
      m1.add(&d1);
      m1.add(&d2);
      Manager m2("manager2");
      m2.add(&m1);
      m2.work();
      return 0;









      share|improve this question












      share|improve this question




      share|improve this question








      edited Jun 5 at 19:40









      rolfl♦

      90.2k13186390




      90.2k13186390









      asked Jun 5 at 18:31









      Abhinav Agarwal

      11916




      11916




















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          3
          down vote













          1. Don't use using namespace std



          That's generally considered bad practice.



          Rather use



          using std::cout;
          using std::cin;
          using std::string;


          if you want to avoid typing these out.



          2. Use interfaces properly and don't mix them up with abstract class implementations




          1. Instead of simply declaring an abstract class, sort out specific interfaces in 1st place



            struct IEmployee 
            virtual const& string name() const = 0; // see 3. regarding const please
            virtual const float& salary() const = 0;
            virtual bool managesOtherEmployees() const = 0; // equivalent to isLeaf() in the
            // common composite pattern
            // examples
            virtual void work() = 0;
            ;



          2. Add functionality as needed:



            struct IManager 
            void add(IEmployee&) = 0;
            void delete(IEmployee&) = 0; // if you have functions to extend the
            // composition, you probably want to have
            // the reverse operation if reasonable.
            // Here it seems to be so, since managers
            // sometimes need to fire team members.
            ;



          3. Provide the abstract class for the common implementation



            class Employee : public IEmployee 
            private:
            string name_; // Don't use prefix '_' for symbols, these are reserved
            // for the compiler and standard library implementations (see 4.)
            float salary_;
            public:
            Employee(string name, float salary) : name_(name), salary_(salary)
            string name() const override
            return name_;

            float salary() const override
            return salary_;

            bool managesOtherEmployees() const override return false;
            ;


          2. leads to an implementation of Developer and Manager classes as follows:



          class Developer : public Employee 
          public:
          Developer(string name,float salary) : Employee(name,salary)
          void work()
          cout << "Developer " << name() << " Workedn";
          // A developer works own.

          ;

          class Manager : public Employee, public IManager
          private:
          vector<std::reference_wrapper<IEmployee>> team_;
          public:
          Manager(string name, float salary) : Employee(name,salary)
          bool managesOtherEmployees() const override return true;
          void add(IEmployee& emp) override
          team_.push_back(std::reference_wrapper<IEmployee>(emp));

          void delete(IEmployee& emp) override
          std::remove(team_.begin(),team_.end(),std::reference_wrapper<IEmployee>(emp));

          void work()
          cout << "Manager " << name() << " Distributed Workn";
          for(auto& emp : team_) // Use range based loops and auto whenever possible (see 5.)
          emp.work();

          // A manager distributes work in team members.

          float salary() const override
          float accumulatedSalary = 0.0;
          for(const auto& emp : team_) // Note const and reference again
          accumulatedSalary += emp.salary() +15000;

          return accumulatedSalary;
          // Salary of a manager is derived from team members.

          ;


          3. Use const qualifiers as much as possible



          If you're declaring a class operation (class member function), decide if this should change the class state in first place.

          Append a const qualifier, if you decide it shouldn't.



          Same for parameters and return values. Usually you don't have to worry about which method by value or by const reference will be more efficient.

          With any sophisticated, modern c++ compiler, you can assume the most efficient emitted assembly code will be chosen.



          Passing/returning by value, still might be prone to generate copies if RVO isn't applicable. Thus I simply prefer to be explicit about that.



          4. Don't use symbol names prefixed with _



          Symbol names prefixed with a single or double underscore (_) are preserved by the c++ standard for compiler internals and standard library implementations.



          It's easy to come over that just using underscores as a postfix for symbols as indication of class member variables:



          template<typename TValue>
          class MyClass
          private:
          TValue myValue_;
          public:
          MyClass(const TValue& myValue) : myValue_(myValue)
          const TValue& myValue() return myValue_; // standard getter signature
          void myValue(const & TValue value) myValue_ = value; // standard setter signature
          ;


          The above pattern will serve 98% of cases unambiguously quite well.



          5. Use range based loop syntax beyond c++98



          Since c++11 standard was established, the language supports range based for() loops of the form



          for(<type spec> el : <container_ref>) /* ... */



          You should use the auto keyword for <type spec>, it can be garnished with const and & as usual, and automatically evaluates a dereferenced Iterator when enumerating the Containers values.






          share|improve this answer























            Your Answer




            StackExchange.ifUsing("editor", function ()
            return StackExchange.using("mathjaxEditing", function ()
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            );
            );
            , "mathjax-editing");

            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "196"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );








             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f195909%2femployees-and-organizational-hierarchy%23new-answer', 'question_page');

            );

            Post as a guest






























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            3
            down vote













            1. Don't use using namespace std



            That's generally considered bad practice.



            Rather use



            using std::cout;
            using std::cin;
            using std::string;


            if you want to avoid typing these out.



            2. Use interfaces properly and don't mix them up with abstract class implementations




            1. Instead of simply declaring an abstract class, sort out specific interfaces in 1st place



              struct IEmployee 
              virtual const& string name() const = 0; // see 3. regarding const please
              virtual const float& salary() const = 0;
              virtual bool managesOtherEmployees() const = 0; // equivalent to isLeaf() in the
              // common composite pattern
              // examples
              virtual void work() = 0;
              ;



            2. Add functionality as needed:



              struct IManager 
              void add(IEmployee&) = 0;
              void delete(IEmployee&) = 0; // if you have functions to extend the
              // composition, you probably want to have
              // the reverse operation if reasonable.
              // Here it seems to be so, since managers
              // sometimes need to fire team members.
              ;



            3. Provide the abstract class for the common implementation



              class Employee : public IEmployee 
              private:
              string name_; // Don't use prefix '_' for symbols, these are reserved
              // for the compiler and standard library implementations (see 4.)
              float salary_;
              public:
              Employee(string name, float salary) : name_(name), salary_(salary)
              string name() const override
              return name_;

              float salary() const override
              return salary_;

              bool managesOtherEmployees() const override return false;
              ;


            2. leads to an implementation of Developer and Manager classes as follows:



            class Developer : public Employee 
            public:
            Developer(string name,float salary) : Employee(name,salary)
            void work()
            cout << "Developer " << name() << " Workedn";
            // A developer works own.

            ;

            class Manager : public Employee, public IManager
            private:
            vector<std::reference_wrapper<IEmployee>> team_;
            public:
            Manager(string name, float salary) : Employee(name,salary)
            bool managesOtherEmployees() const override return true;
            void add(IEmployee& emp) override
            team_.push_back(std::reference_wrapper<IEmployee>(emp));

            void delete(IEmployee& emp) override
            std::remove(team_.begin(),team_.end(),std::reference_wrapper<IEmployee>(emp));

            void work()
            cout << "Manager " << name() << " Distributed Workn";
            for(auto& emp : team_) // Use range based loops and auto whenever possible (see 5.)
            emp.work();

            // A manager distributes work in team members.

            float salary() const override
            float accumulatedSalary = 0.0;
            for(const auto& emp : team_) // Note const and reference again
            accumulatedSalary += emp.salary() +15000;

            return accumulatedSalary;
            // Salary of a manager is derived from team members.

            ;


            3. Use const qualifiers as much as possible



            If you're declaring a class operation (class member function), decide if this should change the class state in first place.

            Append a const qualifier, if you decide it shouldn't.



            Same for parameters and return values. Usually you don't have to worry about which method by value or by const reference will be more efficient.

            With any sophisticated, modern c++ compiler, you can assume the most efficient emitted assembly code will be chosen.



            Passing/returning by value, still might be prone to generate copies if RVO isn't applicable. Thus I simply prefer to be explicit about that.



            4. Don't use symbol names prefixed with _



            Symbol names prefixed with a single or double underscore (_) are preserved by the c++ standard for compiler internals and standard library implementations.



            It's easy to come over that just using underscores as a postfix for symbols as indication of class member variables:



            template<typename TValue>
            class MyClass
            private:
            TValue myValue_;
            public:
            MyClass(const TValue& myValue) : myValue_(myValue)
            const TValue& myValue() return myValue_; // standard getter signature
            void myValue(const & TValue value) myValue_ = value; // standard setter signature
            ;


            The above pattern will serve 98% of cases unambiguously quite well.



            5. Use range based loop syntax beyond c++98



            Since c++11 standard was established, the language supports range based for() loops of the form



            for(<type spec> el : <container_ref>) /* ... */



            You should use the auto keyword for <type spec>, it can be garnished with const and & as usual, and automatically evaluates a dereferenced Iterator when enumerating the Containers values.






            share|improve this answer



























              up vote
              3
              down vote













              1. Don't use using namespace std



              That's generally considered bad practice.



              Rather use



              using std::cout;
              using std::cin;
              using std::string;


              if you want to avoid typing these out.



              2. Use interfaces properly and don't mix them up with abstract class implementations




              1. Instead of simply declaring an abstract class, sort out specific interfaces in 1st place



                struct IEmployee 
                virtual const& string name() const = 0; // see 3. regarding const please
                virtual const float& salary() const = 0;
                virtual bool managesOtherEmployees() const = 0; // equivalent to isLeaf() in the
                // common composite pattern
                // examples
                virtual void work() = 0;
                ;



              2. Add functionality as needed:



                struct IManager 
                void add(IEmployee&) = 0;
                void delete(IEmployee&) = 0; // if you have functions to extend the
                // composition, you probably want to have
                // the reverse operation if reasonable.
                // Here it seems to be so, since managers
                // sometimes need to fire team members.
                ;



              3. Provide the abstract class for the common implementation



                class Employee : public IEmployee 
                private:
                string name_; // Don't use prefix '_' for symbols, these are reserved
                // for the compiler and standard library implementations (see 4.)
                float salary_;
                public:
                Employee(string name, float salary) : name_(name), salary_(salary)
                string name() const override
                return name_;

                float salary() const override
                return salary_;

                bool managesOtherEmployees() const override return false;
                ;


              2. leads to an implementation of Developer and Manager classes as follows:



              class Developer : public Employee 
              public:
              Developer(string name,float salary) : Employee(name,salary)
              void work()
              cout << "Developer " << name() << " Workedn";
              // A developer works own.

              ;

              class Manager : public Employee, public IManager
              private:
              vector<std::reference_wrapper<IEmployee>> team_;
              public:
              Manager(string name, float salary) : Employee(name,salary)
              bool managesOtherEmployees() const override return true;
              void add(IEmployee& emp) override
              team_.push_back(std::reference_wrapper<IEmployee>(emp));

              void delete(IEmployee& emp) override
              std::remove(team_.begin(),team_.end(),std::reference_wrapper<IEmployee>(emp));

              void work()
              cout << "Manager " << name() << " Distributed Workn";
              for(auto& emp : team_) // Use range based loops and auto whenever possible (see 5.)
              emp.work();

              // A manager distributes work in team members.

              float salary() const override
              float accumulatedSalary = 0.0;
              for(const auto& emp : team_) // Note const and reference again
              accumulatedSalary += emp.salary() +15000;

              return accumulatedSalary;
              // Salary of a manager is derived from team members.

              ;


              3. Use const qualifiers as much as possible



              If you're declaring a class operation (class member function), decide if this should change the class state in first place.

              Append a const qualifier, if you decide it shouldn't.



              Same for parameters and return values. Usually you don't have to worry about which method by value or by const reference will be more efficient.

              With any sophisticated, modern c++ compiler, you can assume the most efficient emitted assembly code will be chosen.



              Passing/returning by value, still might be prone to generate copies if RVO isn't applicable. Thus I simply prefer to be explicit about that.



              4. Don't use symbol names prefixed with _



              Symbol names prefixed with a single or double underscore (_) are preserved by the c++ standard for compiler internals and standard library implementations.



              It's easy to come over that just using underscores as a postfix for symbols as indication of class member variables:



              template<typename TValue>
              class MyClass
              private:
              TValue myValue_;
              public:
              MyClass(const TValue& myValue) : myValue_(myValue)
              const TValue& myValue() return myValue_; // standard getter signature
              void myValue(const & TValue value) myValue_ = value; // standard setter signature
              ;


              The above pattern will serve 98% of cases unambiguously quite well.



              5. Use range based loop syntax beyond c++98



              Since c++11 standard was established, the language supports range based for() loops of the form



              for(<type spec> el : <container_ref>) /* ... */



              You should use the auto keyword for <type spec>, it can be garnished with const and & as usual, and automatically evaluates a dereferenced Iterator when enumerating the Containers values.






              share|improve this answer

























                up vote
                3
                down vote










                up vote
                3
                down vote









                1. Don't use using namespace std



                That's generally considered bad practice.



                Rather use



                using std::cout;
                using std::cin;
                using std::string;


                if you want to avoid typing these out.



                2. Use interfaces properly and don't mix them up with abstract class implementations




                1. Instead of simply declaring an abstract class, sort out specific interfaces in 1st place



                  struct IEmployee 
                  virtual const& string name() const = 0; // see 3. regarding const please
                  virtual const float& salary() const = 0;
                  virtual bool managesOtherEmployees() const = 0; // equivalent to isLeaf() in the
                  // common composite pattern
                  // examples
                  virtual void work() = 0;
                  ;



                2. Add functionality as needed:



                  struct IManager 
                  void add(IEmployee&) = 0;
                  void delete(IEmployee&) = 0; // if you have functions to extend the
                  // composition, you probably want to have
                  // the reverse operation if reasonable.
                  // Here it seems to be so, since managers
                  // sometimes need to fire team members.
                  ;



                3. Provide the abstract class for the common implementation



                  class Employee : public IEmployee 
                  private:
                  string name_; // Don't use prefix '_' for symbols, these are reserved
                  // for the compiler and standard library implementations (see 4.)
                  float salary_;
                  public:
                  Employee(string name, float salary) : name_(name), salary_(salary)
                  string name() const override
                  return name_;

                  float salary() const override
                  return salary_;

                  bool managesOtherEmployees() const override return false;
                  ;


                2. leads to an implementation of Developer and Manager classes as follows:



                class Developer : public Employee 
                public:
                Developer(string name,float salary) : Employee(name,salary)
                void work()
                cout << "Developer " << name() << " Workedn";
                // A developer works own.

                ;

                class Manager : public Employee, public IManager
                private:
                vector<std::reference_wrapper<IEmployee>> team_;
                public:
                Manager(string name, float salary) : Employee(name,salary)
                bool managesOtherEmployees() const override return true;
                void add(IEmployee& emp) override
                team_.push_back(std::reference_wrapper<IEmployee>(emp));

                void delete(IEmployee& emp) override
                std::remove(team_.begin(),team_.end(),std::reference_wrapper<IEmployee>(emp));

                void work()
                cout << "Manager " << name() << " Distributed Workn";
                for(auto& emp : team_) // Use range based loops and auto whenever possible (see 5.)
                emp.work();

                // A manager distributes work in team members.

                float salary() const override
                float accumulatedSalary = 0.0;
                for(const auto& emp : team_) // Note const and reference again
                accumulatedSalary += emp.salary() +15000;

                return accumulatedSalary;
                // Salary of a manager is derived from team members.

                ;


                3. Use const qualifiers as much as possible



                If you're declaring a class operation (class member function), decide if this should change the class state in first place.

                Append a const qualifier, if you decide it shouldn't.



                Same for parameters and return values. Usually you don't have to worry about which method by value or by const reference will be more efficient.

                With any sophisticated, modern c++ compiler, you can assume the most efficient emitted assembly code will be chosen.



                Passing/returning by value, still might be prone to generate copies if RVO isn't applicable. Thus I simply prefer to be explicit about that.



                4. Don't use symbol names prefixed with _



                Symbol names prefixed with a single or double underscore (_) are preserved by the c++ standard for compiler internals and standard library implementations.



                It's easy to come over that just using underscores as a postfix for symbols as indication of class member variables:



                template<typename TValue>
                class MyClass
                private:
                TValue myValue_;
                public:
                MyClass(const TValue& myValue) : myValue_(myValue)
                const TValue& myValue() return myValue_; // standard getter signature
                void myValue(const & TValue value) myValue_ = value; // standard setter signature
                ;


                The above pattern will serve 98% of cases unambiguously quite well.



                5. Use range based loop syntax beyond c++98



                Since c++11 standard was established, the language supports range based for() loops of the form



                for(<type spec> el : <container_ref>) /* ... */



                You should use the auto keyword for <type spec>, it can be garnished with const and & as usual, and automatically evaluates a dereferenced Iterator when enumerating the Containers values.






                share|improve this answer















                1. Don't use using namespace std



                That's generally considered bad practice.



                Rather use



                using std::cout;
                using std::cin;
                using std::string;


                if you want to avoid typing these out.



                2. Use interfaces properly and don't mix them up with abstract class implementations




                1. Instead of simply declaring an abstract class, sort out specific interfaces in 1st place



                  struct IEmployee 
                  virtual const& string name() const = 0; // see 3. regarding const please
                  virtual const float& salary() const = 0;
                  virtual bool managesOtherEmployees() const = 0; // equivalent to isLeaf() in the
                  // common composite pattern
                  // examples
                  virtual void work() = 0;
                  ;



                2. Add functionality as needed:



                  struct IManager 
                  void add(IEmployee&) = 0;
                  void delete(IEmployee&) = 0; // if you have functions to extend the
                  // composition, you probably want to have
                  // the reverse operation if reasonable.
                  // Here it seems to be so, since managers
                  // sometimes need to fire team members.
                  ;



                3. Provide the abstract class for the common implementation



                  class Employee : public IEmployee 
                  private:
                  string name_; // Don't use prefix '_' for symbols, these are reserved
                  // for the compiler and standard library implementations (see 4.)
                  float salary_;
                  public:
                  Employee(string name, float salary) : name_(name), salary_(salary)
                  string name() const override
                  return name_;

                  float salary() const override
                  return salary_;

                  bool managesOtherEmployees() const override return false;
                  ;


                2. leads to an implementation of Developer and Manager classes as follows:



                class Developer : public Employee 
                public:
                Developer(string name,float salary) : Employee(name,salary)
                void work()
                cout << "Developer " << name() << " Workedn";
                // A developer works own.

                ;

                class Manager : public Employee, public IManager
                private:
                vector<std::reference_wrapper<IEmployee>> team_;
                public:
                Manager(string name, float salary) : Employee(name,salary)
                bool managesOtherEmployees() const override return true;
                void add(IEmployee& emp) override
                team_.push_back(std::reference_wrapper<IEmployee>(emp));

                void delete(IEmployee& emp) override
                std::remove(team_.begin(),team_.end(),std::reference_wrapper<IEmployee>(emp));

                void work()
                cout << "Manager " << name() << " Distributed Workn";
                for(auto& emp : team_) // Use range based loops and auto whenever possible (see 5.)
                emp.work();

                // A manager distributes work in team members.

                float salary() const override
                float accumulatedSalary = 0.0;
                for(const auto& emp : team_) // Note const and reference again
                accumulatedSalary += emp.salary() +15000;

                return accumulatedSalary;
                // Salary of a manager is derived from team members.

                ;


                3. Use const qualifiers as much as possible



                If you're declaring a class operation (class member function), decide if this should change the class state in first place.

                Append a const qualifier, if you decide it shouldn't.



                Same for parameters and return values. Usually you don't have to worry about which method by value or by const reference will be more efficient.

                With any sophisticated, modern c++ compiler, you can assume the most efficient emitted assembly code will be chosen.



                Passing/returning by value, still might be prone to generate copies if RVO isn't applicable. Thus I simply prefer to be explicit about that.



                4. Don't use symbol names prefixed with _



                Symbol names prefixed with a single or double underscore (_) are preserved by the c++ standard for compiler internals and standard library implementations.



                It's easy to come over that just using underscores as a postfix for symbols as indication of class member variables:



                template<typename TValue>
                class MyClass
                private:
                TValue myValue_;
                public:
                MyClass(const TValue& myValue) : myValue_(myValue)
                const TValue& myValue() return myValue_; // standard getter signature
                void myValue(const & TValue value) myValue_ = value; // standard setter signature
                ;


                The above pattern will serve 98% of cases unambiguously quite well.



                5. Use range based loop syntax beyond c++98



                Since c++11 standard was established, the language supports range based for() loops of the form



                for(<type spec> el : <container_ref>) /* ... */



                You should use the auto keyword for <type spec>, it can be garnished with const and & as usual, and automatically evaluates a dereferenced Iterator when enumerating the Containers values.







                share|improve this answer















                share|improve this answer



                share|improve this answer








                edited Jun 6 at 6:25


























                answered Jun 5 at 20:15









                πάντα ῥεῖ

                3,82431126




                3,82431126






















                     

                    draft saved


                    draft discarded


























                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f195909%2femployees-and-organizational-hierarchy%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Popular posts from this blog

                    Greedy Best First Search implementation in Rust

                    Function to Return a JSON Like Objects Using VBA Collections and Arrays

                    C++11 CLH Lock Implementation