Dynamically allocating objects to Vector

Hello, I signed up today in search of help for this C++ problem I have.

I am being asked to do this:

Adjust your main function so that it:
- presents the user with a menu where they can choose which type of object to create (DONE)

- dynamically allocates a new object of the given type and stores it into an STL vector of vehicles

- calls the populate function for the new object, allowing the user to input its values

I have my functions setup accordingly, but I am struggling to grasp the concept of allocating new objects into a vector. I am getting errors saying the pointers are being skipped through each case.

Here is my current code:

// Testing each object and class in main function
int main()
{
// Declare variables and STL vector
int vectorSize;
int userInput;

// Ask the user to input the length of the vector
cout << "Please enter a vector size: ";
cin >> vectorSize;
cout << endl;

vector < Vehicle * > vehicles(vectorSize);

// Ask the user to select a type of vehicle
cout << "Please select a vehicle type: \n\n 0: Vehicle \n 1: Motor Vehicle" <<
"\n 2: Bicycle \n 3: Car \n 4: Motorcycle \n 5: Motorhome \n 6: Train \n"
<< " 7: Van \n 8: Quit";

// Read user selection
cin >> userInput;
cout << endl;

// Switch statement to create new vehicle objects
switch (userInput)
{
case 0:
// Create (base class) Vehicle object and pointer
vehicles[vectorSize] = new Vehicle("", "", 0);
Vehicle *aVehiclePtr = vehicles[vectorSize];
aVehiclePtr->populate();
break;

case 1:
// Create (base class) Vehicle object and pointer
vehicles[vectorSize] = new MotorVehicle("", "",0, "", "", 0);
Vehicle *aMotorVehiclePtr = vehicles[vectorSize];
aMotorVehiclePtr->populate();
break;

default:
break;
}

Any help would be greatly appreciated.

Tom


Last edited on
When you declare new variables in switch statements, you have to wrap the code in curly braces {} like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
switch (userInput)
{
case 0:
    // Create (base class) Vehicle object and pointer
    {
        vehicles[vectorSize] = new Vehicle("", "", 0);
        Vehicle *aVehiclePtr = vehicles[vectorSize];
        aVehiclePtr->populate();
    }
    break;

case 1: 
    // Create (base class) Vehicle object and pointer
    {
        vehicles[vectorSize] = new MotorVehicle("", "",0, "", "", 0);
        Vehicle *aMotorVehiclePtr = vehicles[vectorSize];
        aMotorVehiclePtr->populate();
    }
    break;

default:
    break;
}
Also, you could just use vehicles[vectorSize]->populate();

I do have to wonder why you are using "vectorSize" here? Would it not be outstepping the bounds of the vector?
Last edited on
Oh yes! That was a stupid mistake with the switch statement! Forgive me haha!

Yes you are absolutely right there. Thanks for your reply. Basically, my program is asking me to create a user defined vector size and storing them accordingly.

I am unsure on how the vector will store a number of objects from 0 until vectorSize.
I think I have made some progress here.

I have created a for loop after to test the user defined vector size and it works.

But I don't know if this is correct at the moment:

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
// For loop to test the vector size
	for (size_t i = 0; i < vehicles.size(); i++)
	{
	// Ask the user to select a type of vehicle
	cout << "Please select a vehicle type: \n\n 0: Vehicle \n 1: Motor Vehicle" <<
		"\n 2: Bicycle \n 3: Car \n 4: Motorcycle \n 5: Motorhome \n 6: Train \n"
		<< " 7: Van \n 8: Quit";

	// Read user selection
	cin >> userInput;
	cout << endl;

	// Switch statement to create new vehicle objects
	switch (userInput)
	{
		case 0:
			{
				// Create a new Vehicle object and populate it
				vehicles[0] = new Vehicle("", "", 0);
				//Vehicle *aVehiclePtr = vehicles[vectorSize];
				//aVehiclePtr->populate();
				// Vector add function
				vehicles[0]->populate();
				break;
			}

		case 1: 
			{
				// Create a new MotorVehicle object and populate it
				vehicles[0] = new MotorVehicle("", "", 0, "", "", 0);
				//Vehicle *aMotorVehiclePtr = vehicles[vectorSize];
				//aMotorVehiclePtr->populate();
				vehicles[0]->populate();
				break;
			}

> I am unsure on how the vector will store a number of objects from 0 until vectorSize.

Read this: http://www.mochima.com/tutorials/vectors.html

Declare Vehicle::populate() as virtual, and then:

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
vector < Vehicle * > vehicles ; // create an empty vector

// LOOP:

// Ask the user to select a type of vehicle
cout << "Please select a vehicle type: \n\n 0: Vehicle \n 1: Motor Vehicle" <<
"\n 2: Bicycle \n 3: Car \n 4: Motorcycle \n 5: Motorhome \n 6: Train \n"
<< " 7: Van \n 8: Quit";

// Read user selection
cin >> userInput;
cout << endl;

// Switch statement to create new vehicle objects
switch (userInput)
{
    case 0: 
        vehicles.push_back( new Vehicle("", "", 0) ) ;
        break;

    case 1: 
        vehicles.push_back( new MotorVehicle("", "",0, "", "", 0) ) ;
        break;

    // etc
}

vehicles.back().populate() ; // virtual  

Last edited on
I'm now currently stuck at this point. Any help would be muchly appreciated!

My main function needs to satisfy the following:

- presents the user with the option to print all of the vehicles currently stored

- asks the user to choose whether to enter a further vehicle or whether to quit

- when the user chooses to quit the program, make sure all dynamically allocated objects are deallocated as appropriate.

I can complete these requirements easily, but I am currently having problems whereby the new motorvehicle object is not printing the correct values. It is only repeating the values of the first object.

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

// Switch statement to create new vehicle objects
	switch (userInput)
	{
		case 0:
			{
				// Create a new Vehicle object and populate it
				vehicles[0] = new Vehicle("", "", 0);
				Vehicle *aVehiclePtr = vehicles[0];
				//aVehiclePtr->populate();
				vehicles[0]->populate();
				break;
			}

		case 1: 
			{
				// Create a new MotorVehicle object and populate it
				vehicles[1] = new MotorVehicle("", "", 0, "", "", 0);
				Vehicle *aMotorVehiclePtr = vehicles[1];
				//aMotorVehiclePtr->populate();
				vehicles[1]->populate();
				break;
			}

		default:
			break;
	}

	cout << "Would you like to print the vehicles? \n\n 0: Yes \n 1: No";
	cin >> vehiclePrint;

	switch (vehiclePrint)
	{
		case 0:
			{
				for (size_t i = 0; i < vehicles.size(); i++)
				{
					vehicles[vectorSize]->display();
				}
				break;
			}

		case 1:
			{
				break;
			}

		default:
			break;

	}
	}







Thanks for your reply JLBorges.

I have an error with the line:

vehicles.back().populate();

Intellisense: expression must have class type.

Any solution would be greatly appreciated.
> I have an error with the line:
> vehicles.back().populate();

What is the error diagnostic from the compiler?

It would help if you posted the code for main(), along with the error/warning messages emitted by the compiler.
Sorry, I understand that was vague. Here is my main.cpp, my virtual functions are all correctly setup in their .h files.

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
// Testing each object and class in main function
int main()
{
	// Declare variables and STL vector
	int vectorSize;
	int userInput;
	int vehiclePrint;
	//int vehiclePopulate;

	// Ask the user to input the length of the vector
	cout << "Please enter a vector size: ";
	cin >> vectorSize;
	cout << endl;

	vector < Vehicle * > vehicles(vectorSize);

	// For loop to test the vector size
	for (size_t i = 0; i < vehicles.size(); i++)
	{
	// Ask the user to select a type of vehicle
	cout << "Please select a vehicle type: \n\n 0: Vehicle \n 1: Motor Vehicle" <<
		"\n 2: Bicycle \n 3: Car \n 4: Motorcycle \n 5: Motorhome \n 6: Train \n"
		<< " 7: Van \n";

	// Read user selection
	cin >> userInput;
	cout << endl;

	// Switch statement to create new vehicle objects
	switch (userInput)
	{
		case 0:
			{
				// Create a new Vehicle object and populate it
				vehicles.push_back(new Vehicle("", "", 0));
				//vehicles[0] = new Vehicle("", "", 0);
				//Vehicle *aVehiclePtr = vehicles[0];
				//aVehiclePtr->populate();
				//vehicles[0]->populate();
				break;
			}

		case 1: 
			{
				// Create a new MotorVehicle object and populate it
				vehicles.push_back(new MotorVehicle("", "", 0, "", "", 0));
				//vehicles[1] = new MotorVehicle("", "", 0, "", "", 0);
				//Vehicle *aMotorVehiclePtr = vehicles[1];
				//aMotorVehiclePtr->populate();
				//vehicles[1]->populate();
				break;
			}

		case 2:
			{
				// Create a new Bicycle object and populate it
				vehicles.push_back(new Bicycle("", "", 0, 0, 0));
				break;
			}

		vehicles.back().populate();

		default:
			break;

	}

	cout << "Would you like to print the vehicles? \n\n 0: Yes \n 1: No";
	cin >> vehiclePrint;

	switch (vehiclePrint)
	{
		case 0:
			{
				for (size_t i = 0; i < vehicles.size(); i++)
				{
					vehicles[vectorSize]->display();
				}
				break;
			}

		case 1:
			{
				break;
			}

		default:
			break;

	}
	}


Error C2228: left of "populate" must have class/struct/union
Last edited on
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
int main()
{
    // Declare variables and STL vector
    // int vectorSize; // ****
    size_t vectorSize ; // just being decent
    
    int userInput;
    int vehiclePrint;
    //int vehiclePopulate;

    // Ask the user to input the length of the vector
    cout << "Please enter a vector size: ";
    cin >> vectorSize;
    cout << endl;

    //vector < Vehicle * > vehicles(vectorSize); // ****
    vector < Vehicle * > vehicles ; // **** empty vector; at this point, vehicles.size() == 0 

    // For loop to test the vector size // ****
    // for (size_t i = 0; i < vehicles.size(); i++) // ***
    // **** loop till vectorSize objects have not been added 
    while( vehicles.size() < vectorSize ) 
    {
        // Ask the user to select a type of vehicle
        cout << "Please select a vehicle type: \n\n 0: Vehicle \n 1: Motor Vehicle" <<
             "\n 2: Bicycle \n 3: Car \n 4: Motorcycle \n 5: Motorhome \n 6: Train \n"
             << " 7: Van \n";

        // Read user selection
        cin >> userInput;
        cout << endl;

        // Switch statement to create new vehicle objects
        switch (userInput)
        {
        case 0:
        {
            // Create a new Vehicle object and populate it
            vehicles.push_back(new Vehicle("", "", 0));
            break;
        }

        case 1:
        {
            // Create a new MotorVehicle object and populate it
            vehicles.push_back(new MotorVehicle("", "", 0, "", "", 0));
            break;
        }

        case 2:
        {
            // Create a new Bicycle object and populate it
            vehicles.push_back(new Bicycle("", "", 0, 0, 0));
            break;
        }

        // vehicles.back().populate(); // **** remove it from here

        default:
            break;

        }
        
        // vehicles.back().populate(); // **** and put it just outside the switch-case

        // ****Error C2228: left of "populate" must have class/struct/union
        // mea culpa, it should have been:
        vehicles.back()->populate() ; // **** populate() is a virtual function 

        //TODO: add a check to verify that a vehicle was added 
        //          (ie. we did not hit the deault case label)
        // call populate() only if a vehicle was added 
        
        cout << "Would you like to print the vehicles? \n\n 0: Yes \n 1: No";
        cin >> vehiclePrint;

        //switch (vehiclePrint) // ***
        if( vehiclePrint == 0 )
        {
            for( size_t i = 0 ; i < vehicles.size(); i++ )
            {
                //vehicles[vectorSize]->display(); // ****
                vehicles[i]->display(); // display() is a virtual function
                // read this first: http://www.mochima.com/tutorials/vectors.html
            }
        }
    }
}
Last edited on
I think JL mistyped - it needs to be ->populate() and not .populate()
Thank you very much for your help. I really appreciate it. You sir, are a legend! :)
I believe I have finished my program now. I would just like to finalise it before submission tomorrow. I have made my destructors virtual to help deallocate memory.

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
// Main Function
int main()
{
	// Declare variables and STL vector
	bool cont = true;
	vector < Vehicle * > vehicles;

	// While loop to check whether program should run
	while (cont)
	{
		// Loop variables
		int optionSelect;
		int createSelect;

		// Ask the user to select a type of vehicle
		cout << "-      Main Menu      -" << endl << endl;
		cout << "Please select an option: " << endl << endl;
		cout << "0: Bicycle" << endl;
		cout << "1: Car" << endl;
		cout << "2: Motorcycle" << endl;
		cout << "3: Motorhome" << endl;
		cout << "4: Train" << endl;
		cout << "5: Van" << endl;
		cout << "6: Print" << endl << endl;

		// Read user selection
		cout << "Selection: ";
		cin >> optionSelect;
		cout << endl;

		// Switch statement to create new vehicle objects
		switch (optionSelect)
		{
			case 0:
				{
					// Create a new Bicycle object and populate it
					vehicles.push_back(new Bicycle("", "", 0, 0, 0));
					vehicles[vehicles.size() -1]->populate();
					break;
				}
			case 1: 
				{
					// Create a new Car object and populate it
					vehicles.push_back(new Car("", "", 0, "", "", 0, "", 0));
					vehicles[vehicles.size() -1]->populate();
					break;
				}
			case 2:
				{
					// Create a new Motorcycle object and populate it
					vehicles.push_back(new Motorcycle("", "", 0, "", "", 0, 0, 0));
					vehicles[vehicles.size() -1]->populate();
					break;
				}
			case 3:
				{
					// Create a new Motorhome object and populate it
					vehicles.push_back(new Motorhome("", "", 0, "", "", 0, 0, 0));
					vehicles[vehicles.size() -1]->populate();
					break;
				}
			case 4: 
				{
					// Create a new Train object and populate it
					vehicles.push_back(new Train("", "", 0, "", "", 0, 0, 0));
					vehicles[vehicles.size() -1]->populate();
					break;
				}
			case 5:
				{
					// Create a new Van object and populate it
					vehicles.push_back(new Van("", "", 0, "", "", 0, 0, 0));
					vehicles[vehicles.size() -1]->populate();
					break;
				}
			case 6:
				{
					// Display all vehicles created
					for (size_t i = 0; i < vehicles.size(); i++)
					{
						vehicles[i]->display();
					}
				}
				break;
			default:
				{
					break;
				}
		}

		// Ask the user to create a new vehicle
		cout << "Create or Quit?" << endl;
		cout << "[1] Create" << endl;
		cout << "[0] Quit" << endl << endl;

		// Retrieve user input
		cout << "Selection: ";
		cin >> createSelect;
		cout << endl;

		// If user selects the option "Quit"
		if (createSelect == 0)
		{
			// Delete objects
			for (size_t i = 0; i < vehicles.size(); i++)
			{
				delete vehicles[i];
			}

			// Ensure vector has no elements
			vector <Vehicle *> vehicles;

			// Quit the program
			cont = false;
		}
	}	
	return 0;
}
closed account (D80DSL3A)
Why declare the local variable vector <Vehicle *> vehicles; on line 111? It's not the same as the one declared on line 6. Try vehicles.clear(); instead.

Otherwise, nice job.
Note that vehicles.back()->populate(); should work for lines 38 and similar.
Ahh thanks for pointing that out on line 111. Much appreciated :)
Topic archived. No new replies allowed.