C++ 对象组合-无法访问对象属性

C++ 对象组合-无法访问对象属性,c++,object-composition,C++,Object Composition,嗨,我对对象合成有问题。 CInvoice类内部需要一个CCustomer对象,因此我创建了一个需要客户的构造函数 在Invoice.h文件中有一行: CCustomer *customer; CCustomer customer; 所提到的构造函数如下所示: CInvoice::CInvoice(CCustomer Customer) { customer = &Customer; } 当我试图在发票上打印客户的名字时,它会返回一些随机字符 CCustomer custom

嗨,我对对象合成有问题。 CInvoice类内部需要一个CCustomer对象,因此我创建了一个需要客户的构造函数

在Invoice.h文件中有一行:

CCustomer *customer;
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
我是否正确地实现了对象组合


我还有一个类元素,我有一个关于它的问题。我应该在不创建发票对象的情况下创建发票元素吗?哪个更符合逻辑?

您应该在构造函数中传递指向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

您应该在构造函数中传入指向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
调用此方法时会发生以下情况:

你打电话给我的客户 customer的副本作为参数推送到堆栈上 副本的地址分配给客户*客户; 构造函数结束 堆栈被释放,客户参数成为无效指针 客户*客户因此指向垃圾 您应该做的是在堆上分配Customer并传递一个指针,例如

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

CInvoice::CInvoice(Customer *customer) {
  this->customer = customer;
}
通过这种方式,您的客户实例在堆中分配,并且它保持您声明它的范围。izomorphius给出的示例也可以使用,但Customer是自动分配到堆栈上的作用域的本地用户,一旦退出函数的作用域,CInvoice中的指针将无效。我希望你能有所不同

调用此方法时会发生以下情况:

你打电话给我的客户 customer的副本作为参数推送到堆栈上 副本的地址分配给客户*客户; 构造函数结束 堆栈被释放,客户参数成为无效指针 客户*客户因此指向垃圾 您应该做的是在堆上分配Customer并传递一个指针,例如

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

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

通过这种方式,您的客户实例在堆中分配,并且它保持您声明它的范围。izomorphius给出的示例也可以使用,但Customer是自动分配到堆栈上的作用域的本地用户,一旦退出函数的作用域,CInvoice中的指针将无效。我希望您能有所不同。

这不会改变您的其余代码

CInvoice::CInvoice(CCustomer &Customer)
{
   customer = &Customer;
}
但也许你是内德

在Invoice.h文件中有一行:

CCustomer *customer;
CCustomer customer;
上面提到的构造函数看起来是这样的??:

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

这不会更改代码的其余部分

CInvoice::CInvoice(CCustomer &Customer)
{
   customer = &Customer;
}
但也许你是内德

在Invoice.h文件中有一行:

CCustomer *customer;
CCustomer customer;
上面提到的构造函数看起来是这样的??:

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

为什么CCustomer*客户是发票的公共可访问属性?我稍后会将其设置为私有。我不是一个有经验的程序员,我通常从公共成员开始,如果需要,成功地将他们设置为私有。顺便说一句,该程序将客户和发票存储在SQL Server数据库中。您认为我应该将CCustomer*或客户ID传递给CInvoice构造函数吗?为什么CCustomer*客户是发票的公共可访问属性?我稍后会将其设置为私有。我不是一个有经验的程序员,我通常从公共成员开始,如果需要,成功地将他们设置为私有。顺便说一句,该程序将客户和发票存储在SQL Server数据库中。您认为我应该将CCustomer*或客户ID传递给CInvoice构造函数吗?提供的代码示例仅在客户和发票对象的生存期相同时有效。如果发票对象的生存期长于客户对象,则问题仍然存在。@JoachimPileborg我知道我只是想更容易理解我的答案的意思。我并不是说这是解决问题的最佳方法,只是简单地指出OP代码的问题。提供的代码示例仅在customer和invoice对象的生存期相同时有效。如果发票对象的生存期长于客户对象,则问题仍然存在。@JoachimPileborg我知道我只是想更容易理解我的答案的意思。我不是说这是解决问题的最好办法,只是用OP的代码来说明问题。我从来没有在C++中使用新的关键字。我一直在C中使用它。它应该被用来指派指针吗?创建这样的对象可以吗:CCustomer customer?不同的是,当您将一个变量声明为CCustomer customer时,它不是一个指针,而是一个在自动调用中分配的对象
在堆栈上的y。在C++中,如果它像java一样,甚至没有堆栈上分配的对象,但它们总是在任何情况下指向对象的引用指针。我总是这样创建对象:CClassName objectname;。现在你告诉我这样做:CClassName*objectname=newcclassname;我理解得对吗?根据上下文,两者都是有效和有意义的。这个话题相当广泛,在评论中讨论它相当复杂。如果你需要一些线索,我们可以继续聊天,但最好的办法是读取动态堆分配和自动堆栈分配之间的具体差异。我从未使用C++中的新关键字。我一直在C中使用它。它是否应该被用来指派指针?创建这样的对象可以吗:CCustomer customer?不同的是,当您将一个变量声明为CCustomer customer时,它不是一个指针,而是一个在堆栈上自动分配的指针。在C++中,如果它像java一样,甚至没有堆栈上分配的对象,但它们总是在任何情况下指向对象的引用指针。我总是这样创建对象:CClassName objectname;。现在你告诉我这样做:CClassName*objectname=newcclassname;我理解得对吗?根据上下文,两者都是有效和有意义的。这个话题相当广泛,在评论中讨论它相当复杂。如果您需要一些线索,我们可以继续聊天,但最好是阅读动态堆分配和自动堆栈分配之间的具体区别。