Cherrypowder
Cherrypowder

Reputation: 57

Understanding OOP Association and Functions (c++)

There's still a whole load of stuff I do not understand about objects and classes in c++, nothing I have read so far has helped me understand any of it and I'm slowly piecing information together from exercises I manage to complete.

Few main points: When an object is created from a class, how can you access the name of the object in a function in another class? What type of variable is the name of the object stored in? is it even stored anywhere after it's creation?

My manual has an example of creating an association between two classes;

    Aggregationclass
{
public:
  ...
private:
  Partclass* partobject_;
  ...
};

What does this actually mean? Aggregationclass can access the object partobject in partclass? what variables can be read by aggregationclass from the partclass?

Here is a exercise I'm stuck on from my c++ OOP introductionary class, that expects me to utilize association between classes. (7(2/2)/11)

It consists of uneditable Car class;

#include <iostream>
#include <string>
using namespace std;

class Car
{
public:
    void Move(int km);
    void PrintDrivenKm();
    Car(string make, int driven_km);
private:
    string make_;
    int driven_km_;
};

Car::Car(string make, int driven_km) : make_(make), driven_km_(driven_km)
{
}

void Car::Move(int km)
{
    driven_km_ = driven_km_ + km;
    cout << "Wroom..." << km << " kilometers driven." << endl;
}
void Car::PrintDrivenKm()
{
    cout << make_ << " car has been driven for" << driven_km_ << " km" << endl;
}

What I have made so far(Person class); I have written most of my questions in comments of this section.

class Person //how do I associate Person class with Car class in a way that makes sense?
{
    public:
    void ChangeCar(string);
        Person(string, string);
    int DriveCar(int);

    private:
    Car* make_;         
    Car* driven_km_;

    string name_;
};

Person::Person(string name, string make) //How do I ensure string make == object created from class Car with same name?
{
    Person::name_ = name;
    Car::make_ = make_;
}
int Person::DriveCar(int x) //Is this the correct way to use a function from another class?
{
    Car::Move(x);
}
void Person::ChangeCar(string y) //this function is wrong, how do I create a function that calls for object from another class with the parameter presented in the call for this function (eg. class1 object(ferrari) = class1 object holds the values of object ferrari from class2?)?
{
    Car::make_ = y;
}

and an uneditable main();

int main()
{
    Car* dx = new Car("Toyota corolla DX", 25000);
    Car* ferrari = new Car("Ferrari f50", 1500);

    Person* driver = new Person("James", dx);

    dx->PrintDrivenKm();
    driver->DriveCar(1000);
    dx->PrintDrivenKm();

    ferrari->PrintDrivenKm();
    driver->ChangeCar(ferrari);
    driver->DriveCar(20000);
    ferrari->PrintDrivenKm();
    return 0;
}

disclaimer: the exercise has been translated from another language, in case of spotting a translation error I failed to notice, please do give notice and I will do my best to fix.

Finished exercise; thank you, u/doctorlove for taking the time with your replies, I can with confidence say that I learned a lot!

    class Person
{
public:
void ChangeCar(Car * y);
    Person(String name, Car * Car);
int DriveCar(int);
private:
Car * Car_;
int x;
string name_;
string y;
};

Person::Person(string name, Car * Car) : name_(name), Car_(Car)
{
  Person::name_ = name;
}
int Person::DriveCar(int x)
{
  Car_->Move(x);
}
void Person::ChangeCar(Car * y)
{
 Car_ = y;
}

Upvotes: 0

Views: 131

Answers (1)

doctorlove
doctorlove

Reputation: 19282

Before talking about pointers, look at the Car class:

class Car
{
public:
    void Move(int km);
    void PrintDrivenKm();
    Car(string make, int driven_km);
private:
    string make_;
    int driven_km_;
};

You can't get to the private stuff from outside. Period. You can make (or construct) one

Car car("Zoom", 42);

Since we can see what the constructor does

Car::Car(string make, int driven_km) : make_(make), driven_km_(driven_km)
{
}

it's clear it saves away the string and int in the private member variables make_ and driven_km_.

Now we can call the public functions on this instance:

car.PrintDrivenKm();
car.Move(101);
car.PrintDrivenKm();

So, we've made a car and called some functions.

We could make a car pointer and call its functions too. We need to delete stuff otherwise we leak.

Car * car = new Car("Zoom", 42);
car->PrintDrivenKm();
car->Move(101);
car->PrintDrivenKm();
delete car;

Now to your problems.

You have a started writing a Person class which has two (private) cars (pointers) make_ and driven_km_. The constructor Person(string, string); takes two strings, but main doesn't send it two strings:

Car* dx = new Car("Toyota corolla DX", 25000);
// ...
Person* driver = new Person("James", dx);

It will be sent a string and a Car *; something like this

Person(string name, Car *car);

So perhaps it only needs one car (pointer), Car *car_?

Now as for calling your car pointer, Car has Move method; an instance method not a static method, so call it on an instance:

int Person::DriveCar(int x)
{
    //Car::Move(x);  //no - which car do we move, not a static on ALL cars
    car_->Move(x);
}

Now, if the person wants to change car, you made person take a string:

void Person::ChangeCar(string y)
{
    //what goes here?
    // you want a Car * from a string...
    //  we did that before
    delete car_; //not exception safe, but ... 
    car_ = new Car(y);
}

Look back at mian:

driver->ChangeCar(ferrari);

so the calling code will try to send a car (pointer) to swap to. So, get the signature right:

void Person::ChangeCar(Car * y)
{
    car_ = y;
}

If you owned the pointers, you would need a destructor to tidy up pointers. Tell whoever set wrote the code in main to delete their pointers!


Edit:

To re-iterate, in any of the Person you can call the methods on the meber variable car_ functions e.g.

void Person::ChangeCar(Car * y)
{
    car_ = y;
    y->PrintDriveKm(); //call a method on a car pointer.
    car_->PrintDriveKm();
}

This is just the same as calling methods on pointers, as mentioned near the top of my answer.

Go back to

Car* dx = new Car("Toyota corolla DX", 25000);
// ...
Person* driver = new Person("James", dx);

From here, in main, you can call

dx->PrintDrivenKm();

From inside the Person constructor,

Person(string name, Car *car) : name_(name), car_(car)
{
}

You can call methods on car (or car_) inside the braces:

Person(string name, Car *car) : name_(name), car_(car)
{
     std::cout << "Hello, " << name << '\n';
     car_->PrintDrivenKm();
}

Of note: Car:: means something in the class/structr/namespace/scope Car - but you want to call instance methods, so need an instance name. Use -> to all methods on pointers to instances. Use . to call methods on instances.

Upvotes: 3

Related Questions