Reputation: 57
I want to make a train class and car class. I want to have three cars inside the train. The cars are pointed to each other so i can easily go from one to another.
class Train{
// link other car, so i can go from one to another
// pointer to the engine
};
class car{
// cargo weight and pointer to next car and way to know we are in caboose
};
This is what I did:
main.cpp
#include <iostream>
#include "Train.h"
int main()
{
Train* engine;
car* cars = new car();
return 0;
}
Header file:
#ifndef TRAIN_H
#define TRAIN_H
class Train
{
public:
Train()
{
int* space = new int [3];
}
~Train();
};
class car
{
public:
int cargo_weight;
int wieght;
car()
{
int* number = new int [3];
}
~car();
car* Next;
private:
car* head;
car* tail;
};
#endif
Upvotes: 0
Views: 315
Reputation: 33932
First, an aside:
Train(): firstCar(nullptr)
{
int* space = new int [3];
}
space
is a pointer to an int. Doesn't do much good if you want to hold Car
s, but what's nasty is space
only exists within the curly braces of Train
's constructor. The three integers it points to are lost. Not deleted or freed, but lost, and without a pointer to tell you where to find those 3 int
s it's damn hard to release their memory. This is called a memory leak and is generally considered a bad scene.
Next, Car
has both head
, tail
, and next
. This makes Car
both a linked list element and a linked list. Rather odd and probably not necessary. Let the Train
act as the linked list. It has reason to know the chain of Car
s while each car has no reason to know anything other than the next, and possibly previous, Car
.
And onward...
It appears that you want to chain up to three Car
s together in a Train
. First thing the Train
needs is a pointer to the first Car
in the chain.
class Train
{
private:
Car * firstCar;
public:
Train(): firstCar(nullptr) // ensure that the first car point at a sentinel value
// otherwise we're in for a while world of hurt later
{
}
~Train();
};
And you'll need a method to add a car.
bool linkCar(Car * newcar)
{
if (firstCar != nullptr) // if there is no first car.
// See told you we'd need a sentinel!
{
firstCar = newcar; // this car is the first car
}
else
{
firstCar->linkCar(newcar); //tell the first car to link to the new car
}
}
This means that Car
needs a linkCar
method
bool linkCar(Car * newcar)
{
if (next != nullptr) // if this car is the last car in the train add the new car here
{
next = newcar;
}
else
{ // not the last car. Keep looking until we find the last car
next->linkCar(newcar);
}
}
And to make that work, Car::next
must be initialised in the constructor to nullptr
.
car():next(nullptr)
{
}
Unfortunately this approach is kind of poor unless the instructor demands you build a singly linked list of cars. For one thing, you need a bunch of extra book-keeping to stop you from adding a fourth car. You may need a bunch of extra logic to release all of the cars you've allocated. You have to make sure that the car-releasing logic is called. And if the instructor wants a doubly linked list, at best what I have above provides a starting point. Fortunately there are dozens, if not thousands, of examples of how to build a doubly linked list on Stack Overflow.
Instead, store a std::vector
of Car
s
class Train
{
private:
std::vector<Car> cars;
public:
Train()
{
}
bool addCar(Car &newcar)
{
if (cars.size() < 3)
{
cars.push_back(newcar);
}
}
};
Note we don't need a destructor anymore because we have nothing that needs destroying. std::vector
handles all of it for us.
Car doesn't need to know about anything but themselves. No link to the next car is required. No destructor is needed because all of car
s resources are self-managed.
class car
{
private:
int cargo_weight;
int weight;
public:
car()
{
}
};
The car
constructor should probably be expanded to set the weights so that each car is ready to go right out of the box.
car(int c_weight, int car_weight):
cargo_weight(c_weight),
weight(car_weight)
{
}
Upvotes: 1