Thread: Inherited classes cannot call constructor

  1. #1
    Registered User
    Join Date
    Apr 2019
    Posts
    14

    Inherited classes cannot call constructor

    Hello, I have an assignment that generally deals with Inherited classes and I'm stuck at a problem where I'm getting an error when I try calling the constructor:
    error: cannot call constructor ‘HourlyEmployee::HourlyEmployee’ directly [-fpermissive]
    employee = HourlyEmployee::HourlyEmployee(sfirstname, slastname, semployeeId, srate, shours);
    This is my parser class where I get the error. The comments are what I tried already:
    Code:
    #include <string>
    #include "StaffMember.h"
    #include "HourlyEmployee.h"
    using namespace std;
    #ifndef STAFFMEMBERPARSER_H
    
    #define STAFFMEMBERPARSER_H
    
    class StaffMemberParser
    {
     
        public:
        static StaffMember* parseStringToMember(string lineToParse)
        {
        string stype, sfirstname, slastname, semployeeId, srate, shours, sbonus; //I initialize the data here
        int pos, pos2, pos3, pos4, pos5, pos6;                           // because it would give me an error otherwise. 
        
            pos = lineToParse.find("/"); 
            stype = lineToParse.substr(0,pos);
            
            pos2 = lineToParse.find("/", pos+1); 
            sfirstname = lineToParse.substr(pos+1,pos2-pos-1);
            
            pos3 = lineToParse.find("/", pos2+1); 
            slastname = lineToParse.substr(pos2+1,pos3-pos2-1);
            
            pos4 = lineToParse.find("/", pos3+1); 
            semployeeId = lineToParse.substr(pos3+1,pos4-pos3-1);
         
            if(stype == "Volunteer")
            {
            //   Volunteer:Volunteer(sfirstname,slastname, semployeeId);
            }
         
            if(stype == "FullTimeEmployee")
            {
            pos5 = lineToParse.find("/", pos4+1); 
            srate = lineToParse.substr(pos4+1,pos5-pos4-1);
           
            pos6 = lineToParse.find("/", pos5+1); 
            sbonus = lineToParse.substr(pos5+1,pos6-pos5-1);
            
            }
            
            if(stype == "HourlyEmployee")
            {
             pos5 = lineToParse.find("/", pos4+1); 
            srate = lineToParse.substr(pos4+1,pos5-pos4-1);
           
            pos6 = lineToParse.find("/", pos5+1); 
            shours = lineToParse.substr(pos5+1,pos6-pos5-1);
            
          //  HourlyEmployee::HourlyEmployee(sfirstname, slastname, semployeeId, srate, shours);
            StaffMember* employee;
           // employee = &(HourlyEmployee(sfirstname, slastname, semployeeId, srate, shours));
            employee =  HourlyEmployee::HourlyEmployee(sfirstname, slastname, semployeeId, srate, shours);   //happens at this line
            //return employee;
            }
        }
    };
    #endif
    Here is the hourlyemployee class:
    Code:
    // Child class
    #include "StaffMember.h" //include the parent class header
    using namespace std;
    #ifndef HOURLYEMPLOYEE_H
    
    #define HOURLYEMPLOYEE_H
    
    class HourlyEmployee : public StaffMember
    {
        
    private:
    double rate;
    int hoursWorked;
    
    public:
    
    HourlyEmployee(string firstName, string lastName, string memberId, double newRate, int newHoursWorked) : StaffMember(firstName, lastName, memberId)
    {
        
        rate = newRate;
        hoursWorked = newHoursWorked;
    } 
    
    void computePay()
    {
        pay = rate*hoursWorked;
    }
    
    //overriding the printInfo function from the parent class
    virtual void printInfo()
    {
    cout << "\nHourly Employee:";
    StaffMember:printInfo();
    cout << "Rate:\t\t\t$" << rate << endl;
    cout << "Hours:\t\t\t$" << hoursWorked << endl;
    }
    };
    #endif
    Staffmember class:
    Code:
    #include <string>
    using namespace std;
    #ifndef STAFFMEMBER_H
    
    #define STAFFMEMBER_H
    
    class StaffMember
    {
        protected:
        string firstName;
        string lastName;
        string memberID;
        double pay = 0.0;
        
        public:
        StaffMember(string newfirstName, string newlastName , string newmemberID)
        {
            firstName = newfirstName;
            lastName = newlastName;
            memberID = newmemberID;
            pay = 0.0;
        }
        
        string getMemberId()
        {
            return memberID;
        }
    
        virtual void computePay() = 0;
        
        virtual void printInfo()
        {
            cout << "\nFirst name:\t\t" << firstName << endl;
            cout << "Last name:\t\t" << lastName << endl;
            cout << "Member ID:\t\t" << memberID << endl;
            cout << "Pay:\t\t\t$" << pay << endl;
        }
        
    };
    #endif
    Main class:
    Code:
    // Assignment #: 7
    //         Name: 
    // EmailAddress:
    //  Description: It displays a menu of choices
    //               (add volunteers, full time employees, or hourly employees,
    //               compute their pay, search a member, list members,
    //               quit, display menu) to a user.
    //               Then it performs the chosen task. It will keep asking a user to
    //               enter the next choice until the choice of 'Q' (Quit) is
    //               entered.
    
    #include <iostream>
    #include <string>
    #include <cstdlib>
    #include <vector>
    #include "StaffMember.h"
    #include "StaffMemberParser.h"
    
    using namespace std;
    
    void printMenu();
    
    
    int main()
    {
        char input1;
        string inputInfo;
        bool operation;
    
        vector<StaffMember *> memberList;
    
    
        printMenu();     // print out menu
    
    
        do
        {
            cout << "What action would you like to perform?" << endl;
            cin >> input1;
    
            switch (input1)
            {
            case 'A':   //Add Member
                cout << "Please enter a member information to add:\n";
                cin >> inputInfo;
      /***********************************************************************************
      ADD your code here to create a pointer to an object of one of child classes of 
      StaffMember class and add it to the memberList
      ***********************************************************************************/
                StaffMemberParser::parseStringToMember(inputInfo); 
     
                break;
            case 'C':   //Compute Pay
      /***********************************************************************************
      ***  ADD your code here to compute the pay for all members the memberList.
      ***********************************************************************************/
                 for (int j=0; j < memberList.size(); j++)
                {
                     memberList.at(j)->computePay();
                }
                
                cout << "pay computed\n";
                break;
            case 'D':   //Search for Member
                cout << "Please enter a memberID to search:\n";
                cin >> inputInfo;
                operation = false;
      /***********************************************************************************
      ***  ADD your code here to search a given memberID. If found, set "found" true,
      ***  and set "found" false otherwise.
      ***********************************************************************************/
                for (int j=0; j < memberList.size(); j++)
                {
                     if (inputInfo == memberList.at(j)->getMemberId())
                     {
                           operation = true;
                     }
                     else
                     {
                           operation = false;
                     }
                }
            
                if (operation == true)
                    cout << "member found\n";
                else
                    cout << "member not found\n";
                break;
            case 'L':   //List Members
      /***********************************************************************************
      ***  ADD your code here to print out all member objects. If there is no member,
      ***  print "no member\n"
      ***********************************************************************************/
                if (sizeof(memberList) == 0)
                 {
                     cout << "no member\n" << endl;
                 }
                 else
                 {
                     cout << "there are members" << endl;
    
                     for (int j=0; j < memberList.size(); j++)
                     {
                         memberList.at(j)->printInfo();
                     }   
                 }
                
                break;
            case 'Q':   //Quit
                for (int j=0; j < memberList.size(); j++)
                {
                    delete memberList.at(j);
                }
                break;
            case '?':   //Display Menu
                printMenu();
                break;
            default:
                cout << "Unknown action\n"  <<endl;
                break;
            }
    
        } while (input1 != 'Q' && input1 != 'q'); // stop the loop when Q is read
    
    }
    
    /** The method printMenu displays the menu to a user **/
    void printMenu()
    {
        cout << "Choice\t\tAction\n"; 
        cout << "------\t\t------\n"; 
        cout << "A\t\tAdd Member\n"; 
        cout << "C\t\tCompute Pay\n"; 
        cout << "D\t\tSearch for Member\n"; 
        cout << "L\t\tList Members\n"; 
        cout << "Q\t\tQuit\n"; 
        cout << "?\t\tDisplay Help\n\n";
    }

  2. #2
    Programming Wraith GReaper's Avatar
    Join Date
    Apr 2009
    Location
    Greece
    Posts
    2,739
    Remove the "HourlyEmployee::" and it should work. Remember, you don't call the constructor, you create an object. The object, upon its creation, calls the constructor.

    Still though, that would be wrong too, because "employee" is a pointer. I don't know what you're trying to do, but if you want to assign a new object to employee you should delete the old object and make a new one.
    Last edited by GReaper; 04-15-2019 at 04:26 PM.
    Devoted my life to programming...

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    The error message seems pretty clear: cannot call constructor ‘HourlyEmployee::HourlyEmployee’ directly

    That is, you should have written:
    Code:
    HourlyEmployee(sfirstname, slastname, semployeeId, srate, shours);
    instead of:
    Code:
    HourlyEmployee::HourlyEmployee(sfirstname, slastname, semployeeId, srate, shours);
    However, this does not solve the problem entirely: you may create an object, but the destination is a pointer. Hence, you would need to write something like this:
    Code:
    StaffMember* employee = new HourlyEmployee(sfirstname, slastname, semployeeId, srate, shours);
    Unfortunately, doing this means that you now have to do manual memory management, which increases the chance of bugs. Therefore, I would recommend that you #include <memory> and use a unique_ptr instead:
    Code:
    std::unique_ptr<StaffMember> employee = std::make_unique<HourlyEmployee>(sfirstname, slastname, semployeeId, srate, shours);
    Now, you can use employee just as you would a StaffMember*, and it would point to an HourlyEmployee, hence allowing the use of polymorphism. At the same time, you don't have to worry about manual memory management as the HourlyEmployee object would be destroyed when the employee unique_ptr goes out of scope before transferring ownership.

    EDIT:
    This does mean that you need to change the return type of parseStringToMember to be a std::unique_ptr<StaffMember>, but unique_ptrs are designed to be cheap to return, so there's no concern. Furthermore, since it looks like your intent is to return the pointer immediately, there's no need to actually have a pointer variable. You could simplify to:
    Code:
    return std::make_unique<HourlyEmployee>(sfirstname, slastname, semployeeId, srate, shours);
    Also, since StaffMember is a polymorphic base class, you should declare its destructor to be virtual, otherwise attempting to destroy an HourlyEmployee through a StaffMember pointer will result in undefined behaviour.
    Last edited by laserlight; 04-15-2019 at 04:37 PM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    Registered User
    Join Date
    Apr 2019
    Posts
    14
    Quote Originally Posted by GReaper View Post
    Remove the "HourlyEmployee::" and it should work. Remember, you don't call the constructor, you create an object. The object, upon its creation, calls the constructor.

    Still though, that would be wrong too, because "employee" is a pointer. I don't know what you're trying to do, but if you want to assign a new object to employee you should delete the old object and make a new one.
    When I tried to remove the "HourlyEmployee::" ,it gave me another error:
    StaffMemberParser.h: In static member function ‘static StaffMember* StaffMemberParser::parseStringToMember(std::string )’:
    StaffMemberParser.h:56:85: error: no matching function for call to ‘HourlyEmployee::HourlyEmployee(std::string&, std::string&, std::string&, std::string&, std::string&)’
    employee = HourlyEmployee(sfirstname, slastname, semployeeId, srate, shours);
    The employee pointer is only a temporary and it returns the values that I passed on.

  5. #5
    Registered User
    Join Date
    Apr 2019
    Posts
    14
    Quote Originally Posted by laserlight View Post
    The error message seems pretty clear: cannot call constructor ‘HourlyEmployee::HourlyEmployee’ directly

    That is, you should have written:
    However, this does not solve the problem entirely: you may create an object, but the destination is a pointer. Hence, you would need to write something like this:
    Code:
    StaffMember* employee = new HourlyEmployee(sfirstname, slastname, semployeeId, srate, shours);
    Unfortunately I am getting the same error as I described above when I try to change it.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    That error message is a little less obvious, but what "no matching function for call" means is that you either have a typo with the function name (unlikely since this is the class name), or your argument list for the function call does not match the parameter list. As it turns out, it is the latter: the last two parameters of the constructor are double and int respectively, but you're passing string arguments. You need to convert those strings to double and int appropriately, e.g., with std::stod and std::stoi.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    Apr 2019
    Posts
    14
    Quote Originally Posted by laserlight View Post
    That error message is a little less obvious, but what "no matching function for call" means is that you either have a typo with the function name (unlikely since this is the class name), or your argument list for the function call does not match the parameter list. As it turns out, it is the latter: the last two parameters of the constructor are double and int respectively, but you're passing string arguments. You need to convert those strings to double and int appropriately, e.g., with std::stod and std::stoi.
    Thank you. That was it, I had forgotten to convert to double and integers. That was something so simple that I've easily overlooked. You saved me hours of work. Now I was able to get my program to run, but I have another problem in the main function hopefully you can help. When you press 'A' to enter an employee , then press 'L' after that, it doesnt list anything. Have I gotten the pointers wrong or forgot to return something?


    Inherited classes cannot call constructor-capture-png
    Last edited by Befiscure45; 04-15-2019 at 06:54 PM.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    That's because you didn't actually add to the vector of pointers. And you really should be using unique_ptr, including for the vector.

    Additionally, instead of a giant switch, separate the parts into functions, then call the functions from within the switch.

    Another thing: declare variables near first use, i.e., stop declaring variables at one go near the top of functions, unless you can provide them with a sensible initial value at that point. Generally, your variables should exist in the smallest scope feasible, unless concerns such as efficiency dictate otherwise. This makes it easier to reason about your program as you only need to deal with the smallest amount of state at any point.

    Oh, and header inclusion guards should go at the very top of headers, before the header includes other headers. Headers should not having using directives or using declarations at file scope; fully qualify names in headers as needed. Feel free to place using directives and using declarations in a local scope in headers though, or to use them in source files after the header inclusions. This helps to avoid namespace pollution and name collisions.

    Yet another thing: you don't need the StaffMemberParser class as it is nothing more than a fancy namespace. I would get rid of it and rename parseStringToMember to parseStaffMember. That you're parsing from a string is obvious by the parameter type.
    Last edited by laserlight; 04-15-2019 at 08:36 PM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    945
    One other thing: sizeof(memberList) gives you the size of the vector object itself, which is a compile-time constant. It's never 0, even when the vector contains no elements. You need to use memberList.size() (which you do in the for loop a few lines down) to get the number of elements in the vector.

  10. #10
    Registered User
    Join Date
    Apr 2019
    Posts
    14
    Quote Originally Posted by christop View Post
    One other thing: sizeof(memberList) gives you the size of the vector object itself, which is a compile-time constant. It's never 0, even when the vector contains no elements. You need to use memberList.size() (which you do in the for loop a few lines down) to get the number of elements in the vector.
    Thank you. I figured out that problem well while i was doing debugging. I additionally forgot to add the Staff pointer to the vectorlist which is why the list function wouldn't work. So now it's working all great! Thanks for your help.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Inherited class constructor
    By Tamim Ad Dari in forum C++ Programming
    Replies: 2
    Last Post: 06-18-2013, 04:30 PM
  2. how to make an inherited constructor private?
    By thedodgeruk in forum C++ Programming
    Replies: 5
    Last Post: 02-04-2011, 11:05 AM
  3. copy array of classes or explicity call constructor
    By Doodle77 in forum C++ Programming
    Replies: 5
    Last Post: 06-10-2007, 11:57 AM
  4. inherited classes and stl container
    By rahulsk1947 in forum C++ Programming
    Replies: 9
    Last Post: 05-05-2007, 02:27 PM
  5. Replies: 3
    Last Post: 03-26-2006, 12:59 AM

Tags for this Thread