Reputation: 2643
I'm learning C++ and having trouble with pointers.
This simple project consists in a invoice that has a pointer to a customer.
Classes:
class Customer {
string name;
public:
Customer(string name) { this->name = name; };
string getName() { return name; };
void changeName(string name) { this->name = name; };
};
class Invoice {
Customer * customer;
public:
Invoice(Customer *customer) { this->customer = customer; };
Customer getCustomer() { return *customer; };
};
Main:
Customer *customer1 = new Customer("Name 1");
Invoice invoice1(customer1);
cout << invoice1.getCustomer().getName() << endl; //Return:Name 1;
How can I use Customer::changeName(string name) in order to make this work:
(...) changeName("Name 2");
cout << invoice1.getCustomer().getName() << endl; //Return:Name 2;
I don't know what I should use to change the customer's name. Or maybe I'm doing something wrong in the class Invoice.
Why change the name through Invoice?
So I can learn how I can learn how to use the pointer before the project starts getting big.
Later I'm going to have a vector of Invoices and a vector of Customers. Getting the pointer to a Customer from a Invoice or from a vector of Customers should be the same.
Thank you,
Eduardo
Upvotes: 0
Views: 3639
Reputation: 66194
If you want this substantially hardened, i've taken such liberties here. Both Customer and Invoice declarations are significantly updated. Compare them to your existing code. Don't just copy this into your code, as it will definitely break a ton of things. Rather, look at it and see if it makes sense to you:
class Customer
{
string name;
public:
Customer(const string& name) : name(name) {};
const string& getName() const { return name; };
void changeName(const string& name) { this->name = name; };
};
class Invoice
{
const Customer& customer;
public:
Invoice(const Customer& customer) : customer(customer) {};
const Customer& getCustomer() const { return customer; };
};
In general (more often than not, anyway) the only times you should need to pass an object by pointer is if there is a chance the object pointer receiver should accept NULL as a valid value. Otherwise use references or smart pointers. Arrays of object pointers to support polymorphic access not withstanding (and even then, smart pointers ftw), this is generally a good rule to follow.
Significant changes made:
Main
Customer customer1("Name 1");
Invoice invoice1(customer1);
// note: invoice now only allows you to obtain a const-reference
// to the customer of the invoice. As such, you can only fire
// const-members on the returned customer reference.
cout << invoice1.getCustomer().getName() << endl; //Return:Name 1;
// without the const-ness of the getCustomer() member and the reference
// it returns, you would have been able to do this:
//
// invoice.getCustomer.changeName("newname");
//
// As it is written now, you can only change a customer name from
// a non-const customer reference (or pointer), and in doing so,
// *all* invoices for that customer will reflect this change.
customer1.changeName("Name 2");
// note: the invoice was not changed, but the customer it references
// was, and we should see that change now.
cout << invoice1.getCustomer().getName() << endl; //Return:Name 2;
I hope this gives you some ideas on how to restrict and harden your object access later on in your project.
Upvotes: 2
Reputation: 2081
Customer getCustomer() { return *customer; };
should be
Customer& getCustomer() { return *customer; };
because in the first case you copy the customer object and so your changes happen in a temporary object that gets thrown away...
in the second you will return a reference to the object you created.
to change name
string newName = "Edu";
invoice1.getCustomer().changeName( newName );
Upvotes: 7
Reputation: 7421
In Invoice
, return the pointer to the Customer
itself, rather than a copy of its dereferenced value:
Customer* getCustomer() { return customer; };
Then you can change the name like so, and the change will affect the actual Customer
object:
invoice1.getCustomer()->changeName("Name2")
Upvotes: 1