one-to-many association

I have to create a one-to-many association for one of my practice assignments with Employee and Managers with Employee class created by manager object. The employee has a method printing out the info.

Here is what I have so far, my question is how do I call everything into the main function? I've seen tutorials online on how to create the classes which I believe i've done

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <string>
#include <vector>

using namespace std;

//class Employee;
//class Manager;


class Employee {
private: 
	string name, id, address, phoneNumber;
	string firstName, lastName;
	//Employee(const Employee &employee);

public:
	Employee(string firstName, string lastName) :firstName(firstName), lastName(lastName){}
	string getname() const { return this->name; }
	string getname1() const { return this->id; }

};

class Manager {
private:
	//string manager1;
	vector<Employee> employeee;
public:
	void addEmployee(Employee employee) {
		employeee.push_back(employee);
	}
};

int main() {




}
Last edited on
You first need to create an instance of the class.

Since you have a constructor which takes a first and last name, give it that.

Employee employee("Tarik", "Neaj");

Now you can use this instance to call functions.

employee.getname(); // I suggest changing name to getName (big N).
Last edited on
I tried that and other stuff, but I get an error saying that no default construct exist so when I do change my constructor to just Employee(), it says no function definition for employee found.
its because your private variable and constructor variables are the same
Doesn't the constructor have to be the same name as the class? If I rename my private variable to something else like Employee1() it says "Function definition for 'Employee1' not found"
He meant this -

Employee(string firstName, string lastName) :firstName(firstName), lastName(lastName){}

It's not good to name the parameter variables the same as your class variables. It can be a mess. Change it to something like -
 
Employee(string firstNameArg, string lastNameArg) :firstName(firstNameArg), lastName(lastNameArg){}


And if it says you dont have a default constructor, you can just create one

Employee() {}
I think an array of Employee pointers would be better. As it stands, it looks like the Employees are a constituent parts of their Manager, rather than associated with her or him.

Andy
Okay thanks a lot for the help I really appreciate it. It's starting to make a lot more sense now. I see where I went wrong with my constructors


Here's my updated code, now I get an error in the main function on line 43 that says "call of an object of a class type without appropriate operator() or conversion function to pointer-to-function type"

Andy, yeah I see what you mean. I'll give that a shot actually makes sense.
Last edited on
I think you also need one other class for your little model to be complete.

People are not employees of their manager...

Andy
@thatfunnydude

You're trying to call a function which doesnt exist? Your function is called getname not getName. Don't call your variables and functions the same thing, it's confusing. Not to mention that your function is commented out.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <iostream>
#include <string>
#include <vector>

using namespace std;

//class Employee;
//class Manager;


class Employee {
private: 
	string id, address, phoneNumber; // removed the variable getName, not really needed at all
	string firstName, lastName;
	//Manager *themanager;
	//Employee(const Employee &employee);
	//Employee1();

public:
	Employee(string firstNameArg, string lastNameArg) :firstName(firstNameArg), lastName(lastNameArg){}
	Employee() {}


	string getName() const { return this->firstName + " " +  lastName; } // changed name to getName and made the function return the persons full name
	//string getname1() const { return this->id; }

};

class Manager {
private:
	//string manager1;
	vector<Employee> employeee;
public:
	void addEmployee(Employee employee) {
		employeee.push_back(employee);
		
	}
};

int main() {

	Employee employee("Tarik", "Neaj");
	cout << employee.getName() << endl; // prints out what the function returns
}
Thank you so much Tarik, I just started OO programming in C++ so i'm fairly new to this. But with your help its starting to make more sense now.
If you got any questions feel free to ask :) It can be confusing in the beginning but you'll get the hang of it (in other words, its gonna get 10 times harder, be ready).
@TarikNeaj

I will just make a couple of minor changes, if you don't mind :+) I am sure you know this stuff, just forgot to put it in
It's more for the benefit of the OP :+)

19
20
21
22
23
24
25
26
27
28
29
30
31
32
public:
	Employee(const string firstNameArg&, // make parameters const
                  const string lastNameArg&) // pass by reference for anything that is a class
        :
        firstName(firstNameArg), lastName(lastNameArg) {}

	Employee() {}

        // no need to disambiguate with this->, when referring to members, already fixed by renaming parameter
	// changed name to getName and made the function return the persons full name
        string getName() const { return firstName + " " +  lastName; } 
	//string getname1() const { return this->id; }

};



@thatfunnydude

Consider making Name a std::vector<std::string> That way you can accommodate multiple middle names, amongst other things. For example, some cultures write their family name first.Name could be a class of it's own, and a variable of that type could be a member of the Person class.

Also need to do what Andy was suggesting:
andywestken wrote:
People are not employees of their manager...


TarikNeaj wrote:
It can be confusing in the beginning but you'll get the hang of it (in other words, its gonna get 10 times harder, be ready).


Exactly right, it's already happening :+) Even if you don't understand it all now, at least you might have some ideas for the future :+)

Good Luck!!
Last edited on
Thank you so much, I really appreciate it. Yeah this is getting a bit confusing with the constructors, methods, classes and objects. I'll definitely need more practice. I ended up finishing it and getting to work here is my final product.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Employee;
class Manager;


class Employee {
public:
    Manager *manager1;
private:
    string id, address, phoneNumber;
    string firstName, lastName;
    
  
    
public:
    Employee(string firstNameArg, string lastNameArg, string phoneNumberArg, string addressArg, string idArg, Manager *managerArg)
    :firstName(firstNameArg), lastName(lastNameArg), phoneNumber(phoneNumberArg), address(addressArg), id(idArg), manager1(managerArg){}
    Employee() {}
    
    
    
    string getName() const { return this->firstName + " " +  lastName + "\n" + phoneNumber + "\n" + address + "\n" + id; }
    
};

class Manager {
    
public:
    string name = "manager1";
private:
    
    vector<Employee> employeee;

public:
    void addEmployee(Employee employee) {
        employeee.push_back(employee);
        
    }
    
    
    
    Employee addEmployee(string firstName, string lastName, string address, string phoneNumber, string id) {
        Employee emp = Employee(firstName, lastName, address, phoneNumber, id, this);
        employeee.push_back(emp);
        
        
        
        cout << emp.getName() << endl;
        
        
        return emp;
    }
};

int main()
{
    
    Manager name;
    Employee employeen = name.addEmployee("David ", "sfsfdg", "sdfgsdg", "dsfgsdg", "sdfgdsg");
    Employee employeen1 = name.addEmployee("Davikd ", "sfsfdg", "sdfgsdg", "dsfgsdg", "sdfgdsg");
    Employee employeen3 = name.addEmployee("Davikd ", "sfsfdg", "sdfgsdg", "dsfgsdg", "sdfgdsg");
    
    cout << employeen.manager1->name << endl;
    
    
    
    
    return 0;
}


My prof ended up saying my vector wasn't really doing anything which I didn't understand why it wasn't. Also said I should never make any attributes public
Hi,

There are some of my comments from my last post that still apply:

make parameters const
pass by reference for anything that is a class
no need to disambiguate with this->, when referring to members, already fixed by renaming parameter


Having using namespace std; isn't good, so I have put std:: before each std thing, Google to see why that is.

I compiled using cpp.sh (the gear icon at the top right a code snippet) with all 3 warning levels set - should should always do this. It produced these warnings, which give clues as to the problems in your code:

In constructor 'Employee::Employee(std::string, std::string, std::string, std::string, std::string, Manager*)':
16:23: warning: 'Employee::lastName' will be initialized after [-Wreorder]
15:25: warning: 'std::string Employee::phoneNumber' [-Wreorder]
21:5: warning: when initialized here [-Wreorder]
15:25: warning: 'Employee::phoneNumber' will be initialized after [-Wreorder]
15:16: warning: 'std::string Employee::address' [-Wreorder]
21:5: warning: when initialized here [-Wreorder]
15:16: warning: 'Employee::address' will be initialized after [-Wreorder]
15:12: warning: 'std::string Employee::id' [-Wreorder]
21:5: warning: when initialized here [-Wreorder]
15:12: warning: 'Employee::id' will be initialized after [-Wreorder]
13:14: warning: 'Manager* Employee::manager1' [-Wreorder]
21:5: warning: when initialized here [-Wreorder]


It's a good idea to initialise the members in the same order as what they are declared in the class definition.

Also consider putting your class definition into a .hpp header file, and the definition of the class member functions into their own .cpp file. Also note how I have formatted the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// Employee.hpp

#pragma once  // not standard C++, but widely supported, can use header guards instead
#include <string>
#include "Manager.hpp"

class Manager;

class Employee {

private:
    std::string id;  // declare one variable per line
    std::string address; 
    std::string phoneNumber; // put a comment about what is valid
    std::string firstName; 
    std::string lastName;
    Manager manager1;
    
public:
    Employee() {}

    Employee( const std::string idArg&,
                    const std::string addressArg&, 
                    const std::string phoneNumberArg&, 
                    const std::string firstNameArg&, 
                    const std::string lastNameArg&,                    
                    const Manager managerArg&)
    :
     firstName(firstNameArg), 
     lastName(lastNameArg), 
     phoneNumber(phoneNumberArg), 
     address(addressArg), 
     id(idArg), 
     manager1(managerArg); {}

    std::string getName() const; 
    
};



1
2
3
4
5
// Employee.cpp

std::string Employee::getName() const { 
return firstName + " " +  lastName + "\n" + phoneNumber + "\n" + address + "\n" + id; 
}


My prof ended up saying my vector wasn't really doing anything which I didn't understand why it wasn't.


Well it is a little messed up there, an Employee has a Manager and the Manager has a vector of employees - that is fine, it reflects the one to many relationship. But it is ruined by going through an employee to get it's manger to add the employee. Instead add some employees to a Manager, and set the Manager for them via the Employee's constructor.

You can use emplace_back to construct an employee in place, rather than creating a new object like you do on line 48. The addEmployee function shouldn't do any printing.

Hope this answers your questions :+)
Last edited on
Topic archived. No new replies allowed.