Help with pointers and vectors

Hi everyone,

A little background: I'm new to C++ and am having some issues with an assignment involving vectors and pointers. I have seen similar questions posted on the forum and elsewhere online but they all involve an array of preset data being fed into the vectors and I have to ask for user input. I've been working on this problem for about a week and have been waiting on instructor feedback for about 4 days now due to the approaching holidays I'm thinking. So, I'm not asking anyone to just give me an answer out of laziness. I really want to understand where my mistakes are.

The assignment:
Implement a class Person with two fields: name and age, and a class Car with 3 fields: model, pointer to the owner (a Person), pointer to the driver (a Person). Write a program that prompts the user to specify people and cars. Store them in a vector <Person*> and a vector <Car*>. Traverse the vector of Person objects and increment their ages by one year. Traverse the vector of cars and print out the car model, owner's name and age, and driver's name and age.

Errors:
I did some googling and the error I was getting from trying to append my vectors originally was because I wasn't passing in any parameters and hadn't defined a default constructor in each class. So I did that and the errors went away, but I'm still not sure I have that portion correct.

When it comes to printing at the end. The error I was getting right at the following line: cars[i].print();
says: "Member reference type 'value_type' (aka 'Car *') is a pointer; maybe you meant to use '->' ? Fix-it Replace "." with "->"
I went ahead and did place the -> there which lets me run my program.

The current error I'm getting using the Xcode compiler is: "Thread 1: EXC_BAD_ACCESS (Code = 1, address = 0 x 0) at the line : return name;
under :
string Person::get_name() const
{
return name; <--- error shows up here
}

Output:
Please enter person's name: bob
Please enter person's age: 22
Is this person an owner or a driver? (owner/driver): owner
Do you have another person to enter for this car? (y/n): n
Do you have another car model to enter? (y/n): n
Model name: crv
Program ended with exit code: 9

Everything on the user's side looks good until after the program prints "Model name: crv" (for example)
So, I'm wondering if either I'm not adding the names to the persons vector correctly or not pointing to the actual value in name correctly or if I've done something wrong in the print() section of my Car class? I've commented the portions I've recently edited out in case I'm on the wrong track.

Any help would be really appreciated. Thanks a lot for looking and for your time answering!
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
#include <iostream>
#include <string>
#include <vector>

using namespace std;

/** 
 A basic Person class to hold people entered by a user
 */
class Person
{
public:
    Person();
    Person(string person_name, int person_age);
    void read();
    void increment_age();
    string get_name() const;
    int get_age() const;
private:
    string name;
    int age;
};

/**
 default constructor for Person with no name and age of 0
 */
Person::Person()
{
    name = "";
    age = 0;
}

/**
 construct a person with a given name and age
 @param person_name the person's name
 @param person_age the person's age
 */
Person::Person(string person_name, int person_age)
{
    name = person_name;
    age = person_age;
}

/** 
 reads in this person object
 */
void Person::read()
{
    cout << "Please enter person's name: ";
    cin >> name;
    cout << "Please enter person's age: ";
    cin >> age;
}

/**
 increments persons age
 */
void Person::increment_age()
{
    age += 1;
}

/**
 gets the name of this person
 @return the person's name
 */
string Person::get_name() const
{
    return name;
}

/**
 get the age of this person
 @return the person's age
 */
int Person::get_age() const
{
    return age;
}


/** 
 a basic car class to hold car models and assign driver or owner
 */
class Car
{
public:
    Car ();
    Car(string m);
    void read();
    void set_owner (Person* p);
    void set_driver (Person* p);
    void print() const;
private:
    string model;
    Person* owner;
    Person* driver;
};

/**
 default constructor for Car with no name and owner 
 and driver set to NULL to initialize
 */
Car::Car()
{
    model = "";
    owner = NULL;
    driver = NULL;
}

/**
 constructs a car class with a given model name
 @param m the model name
 */
Car::Car(string m)
{
    model = m;
    owner = NULL;
    driver = NULL;
}

/**
 Reads in a car object.
 */
void Car::read()
{
    cout << "Please enter car model name: ";
    cin >> model;
}

/** 
 sets the owner for this car
 @param p the owner
 */
void Car::set_owner(Person* p)
{
    //owner = p; --edited--
    *owner = *p;
}

/** 
 sets the driver for this car
 @param p the driver
 */
void Car::set_driver(Person* p)
{
    //driver = p; --edited--
    *driver = *p;
}

/** 
 prints a description of this car
 */
void Car::print() const
{
    cout << "Model name: " << model << "\n"
    << "Owner: ";
    cout << owner->get_name() << " "
    << owner->get_age();
    cout << "\nDriver: ";
    if (owner == driver)
        cout << "same";
    else
        cout << driver->get_name() << " "
        << driver->get_age();
        cout << "\n";
}


int main()
{
    //initializing vectors to accumulate objects
    vector<Car* > cars;
    vector<Person* > people;
    
    /* 
     while there are more cars to add, each car is added to the cars vector
     and for each car model people are added and set as an owner or driver 
     as long as there are more owners and drivers to add
     */
    bool more_cars = true;
    while (more_cars)
    {
        // adding cars to cars vector
        //Car  next_car; --edited--
        //next_car.read(); --edited--
        //cars.push_back(&next_car); --edited--
        
        Car *next_car = new Car();
        next_car->read();
        cars.push_back(next_car);
        
        
        
        /*string models; --edited--
        models = Car::read(*model); --edited--
        Car *next_car = new Car(models); --edited--
        cars.push_back(next_car); --edited-- */
        
        
        bool more_people = true;
        while (more_people)
        {
            // adding people to people vector
            //Person next_person; --edited--
            //next_person.read(); --edited--
            //people.push_back(&next_person); --edited--
            
            Person *next_person = new Person();
            next_person->read();
            people.push_back(next_person);
            
            // setting person as the owner or driver of this car
            cout << "Is this person an owner or a driver? (owner/driver): ";
            string owner_driver;
            cin >> owner_driver;
            if (owner_driver == "owner")
            {
                void set_owner(Person *p);
            }
            else if (owner_driver == "driver")
            {
                void set_driver(Person *p);
            }
            
            // deciding whether or not to continue adding people
            cout << "Do you have another person to enter for this car? (y/n): ";
            string pers_answer;
            cin >> pers_answer;
            if (pers_answer != "y")
            {
                more_people = false;
            }
            
            // for each person in the people vector, increment age by 1
            for (int i = 0; i<people.size(); i++)
            {
                void increment_age();
            }
        }
        
        // deciding whether or not to continue adding cars
        cout << "Do you have another car model to enter? (y/n): ";
        string car_answer;
        cin >> car_answer;
        if (car_answer != "y") more_cars = false;
    }
    
    /* Done adding people and cars. For each car in the car vector
     print the model name and list owners and drivers with ages
     that are associated with that car model
     */
    for (int i = 0; i<cars.size(); i++)
    {
        cars[i]->print();
        cout << "/n";
    }
    return 0;
}
On line 137 and 147, what you had edited out was correct (I assume, from looking at the assignment: No point to using pointers otherwise). You can't do a straight pointer assignment between two classes, because the data is not necessarily sequential (and probably isn't).

Your constructor for the Cars should initialize the pointers to be nullptr, and then test for if an owner/driver already exists before adding one (checking if pointer == nullptr), and if it does, delete the old one before adding another one.

I don't get what you are doing on lines 219 and 223, and I don't think its legal. I think what you meant was:
1
2
3
next_car->set_owner(next_person);
// or
next_car->set_driver(next_person);


Also, don't forget to deallocate the data in the vectors at the end of main before you end the program (I know the OS should do this for you, but its a good habit to get into).

EDIT:
I know this is an assigment, but really, you shouldn't be using a vector of pointers anyway. If you have to, use a vector of std::shared_ptr or std::unique_ptr (not std::auto_ptr). This does the memory deallocation for you, and helps to prevents segfaults or memory leaks.
Last edited on
Thanks NT3. It feels better to be able to dive back into things with some idea of my mistakes.
Topic archived. No new replies allowed.