Salem Alqahtani
Salem Alqahtani

Reputation: 57

How to create a pointer between two classes?

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

Answers (1)

user4581301
user4581301

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 Cars, 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 ints 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 Cars 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 Cars together in a Train. First thing the Train needs is a pointer to the first Carin 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 Cars

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 cars 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

Related Questions