9

皆さんが私を助けてくれるかどうか疑問に思っていました。

ここに私の.hがあります:

Class Doctor {
   const string name;
   public:
       Doctor();
       Doctor(string name);
       Doctor & Doctor::operator=(const Doctor &doc);
}

そして私のメイン:

int main(){
    Doctor d1 = Doctor("peter");
    Doctor d2 = Doctor();
    d2 = d1;
}

operator= 関数を実行したい。誰でも私を助けることができますか?Doctor の const メンバーに注目してください。

************編集:************ 私の主な問題は、Pacient に Doctor があるように、別のクラスに Doctor という属性を持たせたいということです。しかし、私は私の医者を変えることができるようにしたい. 私は医者 A を見ているように、私は医者 B に会いたいと思っています。コードを実行するのが私だったら、次のように言います。

class Patient{
    Doctor &d;
};

ポインタを変更します。ただし、教師の1人が作成したベースコードを使用しており、クラスは次のように定義されています。

class Patient{
     Doctor d;
}

しかし、Patient クラスの setDoctor() を使用すると、コピーを作成するか、変数自体を変更するため、これは不可能だと思います。最初のものは違いがなく、2番目のものは const のために不可能です。私は正しいですか?

4

6 に答える 6

10

あなたはほとんどそこにいます。いくつかの注目すべき点:

  • const名前は修飾されるべきではありません。Aconstは変更できません。これは、まさに代入演算子で必要なことです。

  • C++ キーワードはclassClassコードにあるものとは異なります (コンパイル エラーが発生します)。

  • Michael Burr が指摘しているように、「ただし、クラスに (単純な文字列メンバーの場合のように) 代入を既に適切にサポートしている他のクラスが単に含まれている場合、コンパイラによって生成された暗黙の operator=() は問題なく機能することに注意してください。 ." ここで、あなたの場合、唯一のメンバーstringは適切なop=. したがって、明示的に定義することは冗長です。

  • Meehの解決策はほとんどありません。それが話していない唯一のことは、自己割り当てです。FAQ 12をお読みください。

  • 代入はビッグ 3 メンバー関数FAQ 27.10の 1 つです。調べる。copy ctor、op=、または dtor のいずれかを実装する必要があるということは、通常、他の 2 つも実装する必要があることを意味します。

修正されたコード サンプルは次のようになります。

class Doctor {
  string name;
  public:
    Doctor& operator=(Doctor const& o) { 
         if (&o != this) name = o.name;
         return *this;
    }
  // ...
};
于 2009-04-12T22:53:42.310 に答える
5

例外セーフになるように代入コンストラクターを正しく定義する標準的な方法は、コピーコンストラクターの観点から代入コンストラクターを定義することです。

class Doctor
{
    public:
        Doctor& operator=(Doctor const& rhs)
        {
            if (this != &rhs)
            {
                Doctor  tmp(rhs);  // Use copy constructor here
                this->swap(tmp);   // Now Swap
            }
            return *this;
        }
        void swap(Doctor& rhs) throws()
        {
            std::swap(.....); // swap each member variable.
        }
};

このようにすることで、例外安全になります。
スワップをスローなしのメソッドにする必要があることに注意してください。STLオブジェクトを使用している場合、これは比較的簡単です。ブーストやすべての優れたライブラリと同様に、これらはすべてこの状況でスローなしのスワップを定義するためです(したがって、スイートに従う必要があります)。 )。

これがうまくいかない場合、コピーコンストラクターの使用でうまくいかないでしょう。この時点では、一時的なものにコピー構築しているため、独自のオブジェクトを変更していません。したがって、オブジェクトはまだ変更されていないため、優れた例外安全性を提供しています。

于 2009-04-13T06:08:31.657 に答える
2

宣言は次のとおりですDoctor &operator=(const Doctor &other); (つまり、Doctor:: を削除します)。

そこから const_cast<> を使用してメンバー変数の const-ness を削除し、機能させる必要があります。あなたが選んだ道には失恋しかないことに注意してください。

メンバー宣言から const を削除し、代わりに必要に応じてメンバー関数を const にして、オブジェクトに影響を与えないことを示すことをお勧めします。(たとえば、アクセサー メンバー関数がある場合は、その const: を宣言できますstring getName() const { return m_name; }) 。

于 2009-04-12T22:48:32.557 に答える
1

多くの人が以前に言ったように、メンバーは「const」であり、作成中に初期化する必要があり、変更することは想定されていないことを示しています。そのような場合に代入演算子を作成する必要があり、そのメンバー変数の代入をスキップできない場合は、それを「変更可能」にします。

覚えて; C++ 標準から、「最初に宣言された const 変数の constness をキャストすることは未定義の動作です。」

HTH、アベイ

于 2009-04-13T04:34:28.807 に答える
0

また、戻り値の型を const& に変更します。

const Doctor& operator=(const Doctor &doc);

const を省略すると、次のようなコードはコンパイル可能になりますが、実際には無効です。

(A = B) = C;

これは次のものと同等ではありません: (これはおそらく意図されたものです)

A = B = C;
于 2009-04-13T14:07:46.107 に答える
0

あなたの名前は const であるため、それを「変更」する唯一の方法はコンストラクターを使用することです。= 演算子を使用する場合は、文字列を "unconst" する必要があります。

.. 文字列を「unconst」したくない場合は、コピー コンストラクターを作成することで、多少同等の動作を得ることができます。

Doctor(const &Doctor d);

..そしてそれを実装します:

Doctor::Doctor(const &Doctor d)
   : name(d.name)
{
//Im pretty sure you have access to private attributes here
// My C+ is a bit rusty :) If not, make a const string getName() method
}
于 2009-04-12T22:44:28.353 に答える