0

私はC++を学んでいて、ポインターに問題があります。
この単純なプロジェクトは、顧客へのポインタを含む請求書で構成されています。

クラス:

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; };
};

主要:

Customer *customer1 = new Customer("Name 1");
Invoice invoice1(customer1);

cout << invoice1.getCustomer().getName() << endl; //Return:Name 1;

これを機能させるためにCustomer::changeName(string name)を使用するにはどうすればよいですか?

(...) changeName("Name 2");

cout << invoice1.getCustomer().getName() << endl; //Return:Name 2;

お客様の名前を変更するために何を使用すればよいかわかりません。または、クラスの請求書で何か問題が発生している可能性があります。

なぜ請求書で名前を変更するのですか?
そのため、プロジェクトが大きくなり始める前に、ポインターの使用方法を学ぶことができます。
後で、請求書のベクトルと顧客のベクトルを作成します。請求書または顧客のベクトルから顧客へのポインタを取得することは同じである必要があります。

ありがとう、
エドゥアルド

4

3 に答える 3

7
Customer getCustomer() { return *customer; };

する必要があります

Customer& getCustomer() { return *customer; };

最初のケースでは、顧客オブジェクトをコピーするため、変更は一時オブジェクトで行われ、破棄されます...

2番目に、作成したオブジェクトへの参照を返します。

名前を変更するには

string newName = "Edu";
invoice1.getCustomer().changeName( newName );
于 2012-11-03T23:43:49.590 に答える
2

これを大幅に強化したい場合は、ここでそのような自由を取りました。顧客と請求書の両方の宣言が大幅に更新されます。それらを既存のコードと比較します。これをコードにコピーするだけではいけません。間違いなくたくさんのことを壊してしまうからです。むしろ、それを見て、それがあなたにとって意味があるかどうかを確認してください。

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; };
};

一般に(とにかく、ほとんどの場合)、オブジェクトをポインタで渡す必要があるのは、オブジェクトポインタの受信者が有効な値としてNULLを受け入れる可能性がある場合のみです。それ以外の場合は、参照またはスマートポインターを使用します。耐えられないポリモーフィックアクセスをサポートするためのオブジェクトポインタの配列(そして、それでも、スマートポインタftw)、これは一般的に従うべき良いルールです。

行われた重要な変更:

  • 非const-accessが特に必要でない限り、const参照を使用します
  • クラスには、メンバー変数の最適な構成を保証するための初期化リストがあります。実際、顧客参照メンバーは初期化リストで初期化する必要があるため、Invoiceでは実際に必要です。

主要

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;

これにより、プロジェクトの後半でオブジェクトへのアクセスを制限および強化する方法についてのアイデアが得られることを願っています。

于 2012-11-03T23:55:44.030 に答える
1

で、逆参照された値のコピーではなく、それ自体Invoiceへのポインタを返します。Customer

Customer* getCustomer() { return customer; };

次に、そのように名前を変更できます。変更は実際のCustomerオブジェクトに影響します。

invoice1.getCustomer()->changeName("Name2")
于 2012-11-03T23:52:18.100 に答える