Question

Hi i have a problem with object composition. The class CInvoice needs to have a CCustomer object inside, so I created a constructor that requires a customer.

In Invoice.h file there is a line:

CCustomer *customer;

And the mentioned constructor looks like this:

CInvoice::CInvoice(CCustomer Customer)
{
   customer = &Customer;
}

When I try to print the name of the customer on the invoice it returns some random characters

CCustomer customer("McDonalds", "Boston, Massachusetts", 4);
CInvoice invoice(customer); 

cout << "Customer:" << customer.GetName() << endl; //it prints "McDonalds"
cout << "Invoice.Customer:" << invoice.customer->GetName() << endl; // it prints random characters

Have I implemented the object composition properly?

Also I have a class CInvoiceElement and have a question about it. Should I create invoice elements without having the invoice object created or the other way around? Which is more logical?

Était-ce utile?

La solution

CInvoice::CInvoice(Customer customer)
{
   customer = &Customer;
}

When you call this method what happens is that:

  • you call CInvoice(customer)
  • a copy of customer is pushed onto the stack as the argument
  • the address of the copy is assigned to Customer *customer;
  • the constructor ends
  • stack is released and the customer argument becomes an invalid pointer
  • Customer *customer thus points to garbage

What you should do is to allocate Customer on the heap and pass a pointer, eg.

Customer *customer = new Customer();
CInvoice *invoice = new CInvoice(customer);

CInvoice::CInvoice(Customer *customer) {
  this->customer = customer;
}

In this way your customer instance is allocated in the heap and it persists the scope in which you declare it. The example given by izomorphius works as well but Customer is local to the scope (it's automatically allocated onto stack), once you exit from the scope of the function the pointer inside CInvoice becomes invalid. I hope you get the difference.

Autres conseils

You should pass in the pointer to the CCustomer in the constructor, otherwise you take the address of the copy of CCustomer that is used as argument to the constructor.

Here is what the code should look like:

CInvoice::CInvoice(CCustomer* _customer)
{
   customer = _customer;
}


.... 
CCustomer customer("McDonalds", "Boston, Massachusetts", 4);
CInvoice invoice(&customer); 

cout << "Customer:" << customer.GetName() << endl; //it prints "McDonalds"
cout << "Invoice.Customer:" << invoice.customer->GetName() << endl; // it prints random characters

this will not change the rest of your code..

CInvoice::CInvoice(CCustomer &Customer)
{
   customer = &Customer;
}

but maybe you ned?

In Invoice.h file there is a line:

CCustomer customer;

And the mentioned constructor looks like this??:

CInvoice::CInvoice(const CCustomer &Customer)
: customer(Customer)
{
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top