Weird programming c++ error

Discussion in 'Programmer's Corner' started by mentaaal, Mar 27, 2009.

  1. mentaaal

    Thread Starter Senior Member

    Oct 17, 2005
    451
    0
    Hey guys, I am having a problem with a very simple inheritance program. I have made a base and derived class for a simple assignment. The strange thing is I cannot get the program to compile without including a cout which references one of the used functions in the application file into the base class' constructor. If i ommit this cout statement, the compiler returns the error:
    I tried to rewrite a simple program with the same idea but could not replicate the error. The problem area is highlighted in the definition file below.
    Header file containing base class and derived class prototypes
    Code ( (Unknown Language)):
    1. #include <string>
    2. #include <iostream>
    3. using namespace std;
    4.  
    5. class employee
    6. {
    7. public:
    8.     employee(int eid, const char * name, float p,const char * ptype);
    9.     inline const string & getname() const;
    10.     inline float getpayrate() const;
    11.     inline const string & getpaytype() const;
    12.     float get_pay();
    13.    
    14. protected:
    15.     virtual void pay() =0;//pure virtual function ensures that employee is an Abstract base class    
    16.     int employee_id;
    17.     string employee_name;
    18.     float payrate;
    19.     float tot_pay;
    20.     string paytype;
    21. };
    22.  
    23.  
    24.  
    25.  
    26. class manager : public employee
    27. {
    28. public:
    29.     manager(int Eid, const char *, float P, const char * P_type, int Supers);    
    30.     inline int getsupervisors() const;
    31.     inline void set_supers(int);
    32.     virtual void pay();
    33.  
    34. private:
    35.     int supervisors;
    36.  
    37. };
    38.  
    39.  
    40.  
    Definition file:
    Code ( (Unknown Language)):
    1. #include "headers.h"
    2.  
    3. employee::employee(int eid, const char* name, float p, const char * ptype)
    4. {
    5.     employee_id = eid;
    6.     employee_name = name;
    7.     payrate = p;
    8.     paytype = ptype;
    9.     tot_pay = 0;
    10.     cout << "The value of name is " << name << " the value of ptype is " << ptype << "This is inside employee constructor.\n";
    11.     cout << "Using getname from withiin employee constructor: " << getname() << endl;
    12.     cout << "Using getpayrate() inside employee constructor: " << getpayrate() << endl;
    13.     //cout << "Using getpayrate() inside employee constructor: " << getpaytype() << endl;
    14.     [B]//if the above line is not commented out, the program works[/B]
    15.    
    16. }
    17.  
    18. const string & employee::getname() const
    19. {
    20.     return employee_name;
    21. }
    22.  
    23. float employee::getpayrate() const
    24. {
    25.     return payrate;
    26. }
    27.  
    28. const string & employee::getpaytype() const
    29. {
    30.     return paytype;
    31. }
    32.  
    33. float employee::get_pay()
    34. {
    35.     pay();
    36.     return tot_pay;
    37. }
    38.  
    39. manager::manager(int Eid, const char * Name, float P, const char * P_type, int Supers)
    40. :employee(Eid,Name,P,P_type),supervisors(Supers)
    41. {
    42.     cout << "The value of name is: " << Name << " The value of P_type is " << P_type << endl;
    43. }
    44.  
    45. void manager::pay()
    46. {
    47.     tot_pay = payrate + payrate/100*5*getsupervisors();    
    48. }
    49.  
    50. int manager::getsupervisors() const
    51. {
    52.     return supervisors;
    53. }
    54.  
    55. void manager::set_supers(int supers)
    56. {
    57.     supervisors = supers;
    58. }
    59.  
     
  2. Mark44

    Well-Known Member

    Nov 26, 2007
    626
    1
    Your linker error says something about some stuff being referenced in function main. I'm betting that you have a typo in main.

    Another little thing that I noticed is that in your employee constructor, the first cout call doesn't have an endl at the end. I don't think this is causing the linker problem, though.
    Mark
     
  3. mentaaal

    Thread Starter Senior Member

    Oct 17, 2005
    451
    0
    Hi Mark,
    Well its definitely not a typo as if comment out the getpayrate() function in the employee constructor, then i cant use it in main() ! I have tried fiddling with the code in main and its fine. I will include it later as I must have forgotten to include it the first time.

    What happens is wherever I reference one of the functions like getpayrate(), the linker complains and gives the location that I have referenced it at.
    CRAZY!
     
  4. Mark44

    Well-Known Member

    Nov 26, 2007
    626
    1
    The linker is mentioning main, so that would be a good place to look.
     
  5. mentaaal

    Thread Starter Senior Member

    Oct 17, 2005
    451
    0
    There really is nothing wrong with the code in main that i can see anyway.

    Code ( (Unknown Language)):
    1. #include "manager.h"
    2. #include "employee.h"
    3. #include <iostream>
    4. #include <string>
    5. using namespace std;
    6.  
    7. int main()
    8. {
    9.     manager m1(1,"Greg",3400.0,"Monthly",20);
    10.    
    11.     cout << endl << endl;
    12.     cout << "M1 is getting paid " << m1.get_pay() << endl;
    13.     cout << ((m1.getpaytype() == "monthly")?" per month.\n":" per week.\n");
    14.     cout << m1.getname() << endl;
    15.  
    16.     cout << m1.getname() << endl;
    17.     cout << m1.getpayrate() << endl;
    18.  
    19.    
    20.  
    21.     return 0;
    22. }
     
  6. thatoneguy

    AAC Fanatic!

    Feb 19, 2009
    6,357
    718
    You left out a word.

    In the definitions, you have:
    Code ( (Unknown Language)):
    1. manager::manager(int Eid, [B]const char * [SIZE=5]Name[/SIZE][/B], float P, const char * P_type, int Supers)
    In the class, you have:
    Code ( (Unknown Language)):
    1. manager(int Eid, [B]const char *[/B], float P, const char * P_type, int Supers);
    Not sure if it is related, but it might be an issue later on.
     
  7. mentaaal

    Thread Starter Senior Member

    Oct 17, 2005
    451
    0
    Hi, thanks for that, i stuck in Name but it didnt do anything. In the class header, it is allowed to have the prototype empty of names of the variables.

    I will ask my lecturer tomorrow and see if he can see why this happening although i doubt it :)
     
  8. thatoneguy

    AAC Fanatic!

    Feb 19, 2009
    6,357
    718
    Can you zip your project and attach it to a post?

    I feel dirty admitting I have M$ VS available.
     
  9. mentaaal

    Thread Starter Senior Member

    Oct 17, 2005
    451
    0
    Sure thing, its enclosed in the attachment. Thanks for your help!

    I'd happily stick at it myself and I usually do, but i have already been at it for ages, and havent a notion of what it could be
     
  10. thatoneguy

    AAC Fanatic!

    Feb 19, 2009
    6,357
    718
    Your problem is with paytype and scope. Strong hints in bold

    You are calling paytype with payrate, also...

    Here is the output, I have a different version of studio (08 Enterprise), so project won't export:
    Code ( (Unknown Language)):
    1.  
    2. The value of name is Greg the [B]value of ptype is Monthly[/B]
    3. This is inside employee constructor.
    4. Using getname from withiin employee constructor: Greg
    5. Using getpayrate() inside employee constructor: 3400
    6. [B]Inside constructor, paytype is:  per week.[/B]
    7. The value of name is: Greg [B]The value of P_type is Monthly[/B]
    8.  
    9.  
    10. M1 is getting paid 6800  per week.
    11. Greg
    12. 3400
    13.  
     
  11. mentaaal

    Thread Starter Senior Member

    Oct 17, 2005
    451
    0
    Well I cannot for the life of me see the problem, I noticed your message and tried it again myself but the results of the cout in the constructor say monthly as well as the couts in main.

    I have re-written the entire thing from scratch and it works problem free. I am guessing I have made some weird typo or mistake somewhere and just cant see it. I shudder to think how difficult it must be to debug thousands of lines of code in industry.

    Edit: This is unbelievable! It happened again on my new program and I am back to square one again. Could you give me a bigger hint as to what the problem is? Its driving me nuts!

    Code ( (Unknown Language)):
    1. #ifndef EMPLOYEE_H
    2. #define EMPLOYEE_H
    3.  
    4. #include <string>
    5. using namespace std;
    6.  
    7. //Given the following class which will be used as the base class to represent a assembly line in a local factory:
    8.  
    9. class employee
    10. {
    11. public:
    12.   employee(int id, string name, float p);
    13.   inline const string & getname() const;
    14.   inline float getpayrate() const;
    15.   virtual float pay(float hours) const =0; //ensures that employee is abstract and cannot be instantiated.
    16.  
    17. protected:
    18.   int employee_id;
    19.   string emp_name;
    20.   float payrate;
    21. };
    22.  
    23. #endif
    24. /*Create 3 other classes that are derived from the class employee:
    25.  
    26. manager - is a salaried wage, looks after a supervisor
    27. supervisor - is a salaried wage, looks after several line employees
    28. line_employee - is a weekly wage
    29.  
    30. You are required to write the complete C++ program to test your base and derived classes.
    31. Feel free to add any member functions or variables to the derived classes to further demonstrate your knowledge of inheritance.*/
    Code ( (Unknown Language)):
    1. #include "employee.h"
    2. #include <iostream>
    3. using namespace std;
    4. employee::employee(int id, std::string name, float p)
    5. :employee_id(id),emp_name(name),payrate(p)
    6. {
    7.     //cout << "this is a test.\n";
    8.     //cout << getname() << endl;
    9.     //cout << getpayrate() << endl;
    10. }
    11.  
    12. const string & employee::getname() const
    13. {
    14.     return emp_name;
    15. }
    16.  
    17. float employee::getpayrate() const
    18. {
    19.     return payrate;
    20. }
    21.  
    22.  
    23.  
    Code ( (Unknown Language)):
    1. #ifndef MANAGER_H
    2. #define MANAGER_H
    3.  
    4. #include "employee.h"
    5.  
    6. class manager : public employee //derived class of employee
    7. {
    8. public:
    9.     manager(int Id, string Name, float P, int sups);
    10.     inline int get_sups() const;
    11.     virtual float pay(float hours) const; //function overload
    12.  
    13. private:
    14.     int supervisors;
    15.  
    16. };
    17.  
    18. #endif
    19.  
    Code ( (Unknown Language)):
    1. #include "manager.h"
    2.  
    3. manager::manager(int Id, std::string Name, float P, int sups)
    4. :employee(Id,Name,P),supervisors(sups)
    5. {}
    6.  
    7. int manager::get_sups() const
    8. {
    9.     return supervisors;
    10. }
    11.  
    12. float manager::pay(float hours) const
    13. {
    14.     return hours*payrate + payrate/100*8*supervisors*hours;
    15. }
    Code ( (Unknown Language)):
    1. #include <iostream>
    2. using namespace std;
    3.  
    4. #include "employee.h"
    5. #include "manager.h"
    6.  
    7. int main()
    8. {
    9.     manager test(1,"blah",20.0,20);
    10.     cout << test.getname() << test.getpayrate() << endl;
    11.    
    12.    
    13.     return 0;
    14. }
    Well I am going to put this problem down to the compiler being stupid. In the very first program, what i had to change to make this work was: revoving the inline const string & and replace with just string for getname and getpayrate. Funnily enough when I replace the function with how it was before, i.e. inline const string &, it works perfectly, but here is the kicker:

    WHEN I PUT IT ALL BACK IN AS SAID, THEN GO TO COMPILE IT WHILST THE DEFINITION WINDOW IS OPEN AS OPPOSED TO THE HEADER WINDOW, THE PROGRAM REVERTS BACK TO THE DISCUSSED ERRORS!

    I have narrowed it down to the inline function, when i add the inline function to the prototype, the compiler says:
    Skipping... (no relevant changes detected)
    but when i change the view to the definition file, the error is back. And the really funny thing is, if I then remove the inline function, and to to recompile it whilst looking at the header, the compiler still issues the error, then only way to get rid of it then is to go back to the definition file and compile it there!

    Could someone explain this response to me or is it a bug? Is it allowed to say:
    inline const string & function_name(int argument);

    Edit: a similar occurrence happens if manually rebuilding the solution is done. For some reason, the compiler skips rebuilding the project after putting in inline if still in the header, but when another file is viewed, the project is rebuilt and the error issued.
     
    Last edited: Mar 31, 2009
  12. Mark44

    Well-Known Member

    Nov 26, 2007
    626
    1
    I'm pretty sure the comparison here is your problem:
    Code ( (Unknown Language)):
    1.  
    2. cout << ((m1.getpaytype() == "monthly")?" per month.\n":" per week.\n");
    3.  
    m1.getpaytype() evaluates to a string, as does "monthly". The value of a string literal is its address in memory, NOT the value of the characters in the string. Since you're using the <string> header, I don't think it offers a function to compare strings (although it might), in which case you'll need to use a standard library function such as strcmp() to make the comparison.

    Mark
     
  13. thatoneguy

    AAC Fanatic!

    Feb 19, 2009
    6,357
    718
    Try this in the class where you output tests:

    Code ( (Unknown Language)):
    1.  
    2. #include "employee.h"
    3. #include <iostream>
    4. using namespace std;
    5. employee::employee(int id, std::string name, float p)
    6. :employee_id(id),emp_name(name),payrate(p)
    7. {
    8.     cout << "this is a test.\n";
    9.     cout << getname() << endl;
    10.     cout << getpayrate() << endl;
    11.    [B] cout << getpaytype() << endl;[/B]
    12.  
    13. }
    14.  
    15. const string & employee::getname() const
    16. {
    17.     return emp_name;
    18. }
    19.  
    20. float employee::getpayrate() const
    21. {
    22.     return payrate;
    23. }
    24.  
     
  14. thatoneguy

    AAC Fanatic!

    Feb 19, 2009
    6,357
    718
    Here's the source for what worked, never thought of just posting it:rolleyes::

    application
    Code ( (Unknown Language)):
    1.  
    2. #include "manager.h"
    3. #include "employee.h"
    4. #include <iostream>
    5. #include <string>
    6. using namespace std;
    7.  
    8. int main()
    9. {
    10.     manager m1(1,"Greg",3400.0,"Monthly",20);
    11.    
    12.     cout << endl << endl;
    13.     cout << "M1 is getting paid " << m1.get_pay() << " ";
    14.     cout << ((m1.getpaytype() == "monthly")?" per month.\n":" per week.\n");
    15.     cout << m1.getname() << endl;
    16.     cout << m1.getpayrate() << endl;
    17.  
    18.    
    19.  
    20.     return 0;
    21. }
    22.  

    employee-definition
    Code ( (Unknown Language)):
    1.  
    2. #include "employee.h"
    3.  
    4. employee::employee(int eid, const char* name, float p, const char * ptype)
    5. {
    6.     employee_id = eid;
    7.     employee_name = name;
    8.     payrate = p;
    9.     paytype = ptype;
    10.     tot_pay = 0;
    11.     cout << "The value of name is " << name << " the value of ptype is " << ptype << "This is inside employee constructor.\n";
    12.     cout << "Using getname from withiin employee constructor: " << getname() << endl;
    13.     cout << "Using getpayrate() inside employee constructor: " << getpayrate() << endl << "Inside constructor, paytype is: " ;
    14.     cout << ((getpaytype() == "monthly")?" per month.\n":" per week.\n");
    15.    
    16. }
    17.  
    18. const string & employee::getname() const
    19. {
    20.     return employee_name;
    21. }
    22.  
    23. float employee::getpayrate() const
    24. {
    25.     return payrate;
    26. }
    27.  
    28. const string & employee::getpaytype() const
    29. {
    30.     return paytype;
    31. }
    32.  
    33. float employee::get_pay()
    34. {
    35.     pay();
    36.     return tot_pay;
    37. }
    38.  

    mgr-def
    Code ( (Unknown Language)):
    1.  
    2. #include "manager.h"
    3.  
    4. manager::manager(int Eid, const char * Name, float P, const char * P_type, int Supers)
    5. :employee(Eid,Name,P,P_type),supervisors(Supers)
    6. {
    7.     cout << "The value of name is: " << Name << " The value of P_type is " << P_type << endl;
    8. }
    9.  
    10. void manager::pay()
    11. {
    12.     tot_pay = payrate + payrate/100*5*getsupervisors();    
    13. }
    14.  
    15. int manager::getsupervisors() const
    16. {
    17.     return supervisors;
    18. }
    19.  
    20. void manager::set_supers(int supers)
    21. {
    22.     supervisors = supers;
    23. }
    24.  
    25.  
     
  15. mentaaal

    Thread Starter Senior Member

    Oct 17, 2005
    451
    0
    Hey guys, thanks for the additional posts, much appreciated. Well I am not sure if you saw my last message, I had edited my last post as opposed to just replying again but it turns out that the inline function was causing the problems! I dont understand why or how but that was it. const string & doesnt work with inline perhaps?
     
Loading...