Search code examples
c++object-composition

Object composition - cannot access object properties


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?


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.