2013-01-08 82 views
1

嗨,我有一個對象組成的問題。 CInvoice類需要內部有一個CCustomer對象,所以我創建了一個需要客戶的構造函數。對象組成 - 無法訪問對象屬性

在Invoice.h文件有一行:

CCustomer *customer; 

並且所提到的構造是這樣的:

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 

我是否正確實現了對象組合?

另外我有一個類CInvoiceElement,並有一個關於它的問題。我是否應該創建發票元素而無需創建發票對象或其他方式?哪個更合乎邏輯?

+1

爲什麼CCustomer *客戶發票的可公開訪問的屬性? – tmaric

+0

稍後我會將其設置爲private。我不是一個有經驗的程序員,我通常從公共成員開始,如果需要的話,可以將它們設置爲私有的。順便說一下,該程序將客戶和發票存儲在SQL-Server數據庫中。您認爲我應該將CCustomer *還是客戶ID傳遞給CInvoice構造函數? – BuahahaXD

回答

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

當調用此方法會發生什麼情況是:

  • 你叫CInvoice(customer)
  • 客戶的副本作爲參數推入堆棧
  • 複製的地址被分配爲t o Customer *customer;
  • 構造結束
  • 堆棧被釋放和客戶爭論變成了無效的指針
  • Customer *customer從而指向垃圾

你應該做的是在堆上分配客戶,並通過一個指針,例如。

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

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

這樣你的客戶實例在堆中分配,並堅持該聲明它的範圍。 izomorphius給出的例子也可以工作,但Customer對於作用域是本地的(它會自動分配到堆棧中),一旦退出函數範圍,CInvoice中的指針變得無效。我希望你有所作爲。

+0

我從來沒有在C++中使用過新的關鍵字(我一直在C#中使用它)。它應該用於分配指針嗎?創建這樣的對象是否可行:CCustomer客戶; ? – BuahahaXD

+0

這是不同的,當你將一個變量聲明爲'CCustomer customer'時,它不是一個指向'CCustomer'實例的指針,而是一個自動分配在堆棧上的東西。在C#中(從來沒有用過),如果它像Java一樣,你甚至沒有在堆棧上分配對象,但它們始終是對象的引用(指針)。 – Jack

+0

你正在顛倒我的C++知識。我總是用來創建像這樣的對象:CClassName objectname ;.現在你告訴我這樣做:CClassName * objectname = new CClassName();我理解它嗎? – BuahahaXD

4

您應該將指針傳遞給構造函數中的CCustomer,否則將用作參數的CCustomer副本的地址傳遞給構造函數。

下面是代碼應該是什麼樣子:

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 
+0

只要客戶和發票對象的生命週期相同,提供的代碼示例就是有效的。如果'invoice'對象的生命週期比'customer'對象長,問題仍然存在。 –

+0

@JoachimPileborg我知道我只是想讓我更容易理解我的答案。我並不是說這是解決問題的最佳方式,只是簡單地指出OP代碼的問題。 –

0

這不會改變你的代碼的其餘部分..

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

但也許你定義?

In Invoice。.h文件中有一行:

CCustomer customer; 

並且所提到的構造看起來像這樣??:

CInvoice::CInvoice(const CCustomer &Customer) 
: customer(Customer) 
{ 
}