4

Ich fragte mich, ob ihr mir helfen könnt.Operator = Überladung mit Const Variable in C++

Hier sind meine .h:

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

und mein Haupt:

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

ich den Operator = Funktion tun wollen. Kann mir jemand helfen? Beachten Sie das konstante Mitglied auf Doktor.

************ EDIT: ********* Mein Hauptproblem ist, dass ich möchte, dass eine andere Klasse ein Attribut hat, das ein Doktor ist, wie ein Pacient hat Arzt. Aber ich möchte meinen Doktor wechseln können. Wie ich Arzt A sehe, aber ich möchte Arzt B. Das würde mit einem SetDoctor-Funktion in meiner anderen Klasse (Pacient) getan werden. Wenn ich es wäre, würde ich so etwas sagen:

und dann den Zeiger ändern. Allerdings verwende ich eine Code-Basis von einem des Lehrers gemacht und es die Klasse definiert wie:

class Patient{ 
    Doctor d; 
} 

Aber ich denke, das ist unmöglich, weil mit einem setDoctor zu tun() in der Patientenklasse würde ich entweder machen eine Kopie oder ändern Sie die Ausgabe selbst. Die erste macht keinen Unterschied und die zweite ist unmöglich wegen der const. Habe ich recht?

+0

Warum machen Sie es const, wenn es sich deutlich ändert? –

+0

Aber es ist nicht initialisiert ... Ich erinnere mich nicht sehr gut, aber ich denke, es kann nicht ändern, sobald initialisiert. – jasonco

+0

Gibt es einen Grund, warum Sie nicht der Kopierkonstruktor sind? –

Antwort

7

Sie sind fast da. Wenige nennenswerte Punkte:

  • Der Name sollte nicht const qualifiziert sein. Eine const kann nicht geändert werden, was genau wir im Zuweisungsoperator wollen.

  • Die C++ Schlüsselwort ist class und nicht Class wie Ihr Code hat (es wird Ihnen Fehler kompilieren geben)

  • Als Michael Burr stellt fest: „Es ist zu beachten Sie aber, dass, wenn die Klasse einfach andere enthält Klassen, die die Zuweisung bereits richtig unterstützen (wie in diesem Fall mit einem einfachen String-Member), wird der implizite, vom Compiler generierte Operator =() problemlos funktionieren. " Hier, in Ihrem Fall, hat das einzige Mitglied string eine ordnungsgemäße op=. Das explizite Definieren ist also redundant.

  • Meehs Lösung ist fast da. Das einzige, worüber nicht gesprochen wird, ist die Selbstaufgabe. Lesen Sie FAQ 12.

  • Zuordnung ist eine der großen drei Mitglieder Funktionen FAQ 27.10. Schlag es nach. Es besagt, dass die Anforderung, eines von copy ctor, op = oder dtor zu implementieren, normalerweise bedeutet, dass Sie auch die anderen beiden implementieren müssen.

Der Code korrigiert Probe in etwa so sein sollte:

class Doctor { 
    string name; 
    public: 
    Doctor& operator=(Doctor const& o) { 
     if (&o != this) name = o.name; 
     return *this; 
    } 
    // ... 
}; 
+0

Es sollte jedoch beachtet werden, dass, wenn die Klasse einfach andere Klassen enthält, die die Zuweisung bereits richtig unterstützen (wie in diesem Fall mit einem einfachen String-Member), der implizite, vom Compiler generierte Operator =() problemlos funktioniert. –

+0

@Michael: Ja, ich hätte das hinzufügen sollen. Ich werde meinen Beitrag bearbeiten. – dirkgently

+0

@Michael: Das Problem const gilt auch, wenn wir haben "Doctor d1 = NULL; Doktor d2 = Doktor(); d1 = d2;" ? –

0

Da Ihr Name const ist, ist die einzige Möglichkeit zum "Ändern" der Konstruktor. Wenn Sie den Operator = verwenden möchten, müssen Sie die Zeichenfolge "nicht verankern".

.. wenn Sie nicht wollen, zu "unconst" die Zeichenfolge, könnten Sie etwas gleich Verhalten erhalten, indem Sie eine Kopie-Konstruktor erstellen:

Doctor(const &Doctor d); 

.. und umzusetzen:

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

Sie müssen die Zeichenfolge in der Initialisierungsliste initialisieren, nicht im Konstruktor-Body: Doctor :: Doctor (const Doctor & d): name (d.name) {} –

+0

Aaah Ja, ich wusste, ich habe etwas vergessen :) Ich bearbeite meine Antwort – cwap

+0

hinzufügen, um Dribeas 'Korrektur, Sie können auch nicht ändern, die Zeichenfolge im Konstruktor. Die Zeichenfolge ist const. Der einzige, der die Zeichenkette ändern kann, ist der Konstruktor der Zeichenkette selbst. –

2

die Erklärung ist Doctor &operator=(const Doctor &other); (dh entfernen Sie den Arzt: :)

von dort würden Sie die const-ness const_cast < > entfernen o verwenden müssen f die Elementvariable, damit es funktioniert. Beachten Sie, dass nur Herzschmerz in dem Pfad liegt, den Sie gewählt haben.

Ich würde empfehlen, const aus der Member-Deklaration zu entfernen und stattdessen Member-Funktionen const wie erforderlich zu machen, um zu zeigen, dass sie das Objekt nicht beeinflussen werden. (Zum Beispiel, wenn Sie eine Accessor-Member-Funktion haben, können Sie das const: string getName() const { return m_name; })

+0

In der Tat .. const_cast <> wird vom Teufel gemacht :) Deshalb habe ich es meiner Antwort nicht hinzugefügt. – cwap

1

Wie viele gesagt haben, früher, das Element ‚const‘ zeigt an, dass es während der Erstellung initialisiert werden muss, und es ist nicht soll sich ändern. Wenn überhaupt ein Zuweisungsoperator für solche Fälle geschrieben werden muss und Sie die Zuweisung dieser Elementvariable nicht überspringen können, dann machen Sie sie "änderbar".

Denken Sie daran; Nach dem C++ - Standard ist das Verwerfen der Konstanz einer ursprünglich deklarierten const-Variablen ein undefiniertes Verhalten.

HTH, Abhay

2

Der Standardweg die Zuordnung Konstruktor korrekt zu definieren, so dass es sicher ist, außer es ist im Hinblick auf die Copykonstruktor zu definieren.

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

Dadurch macht es die Ausnahme sicher.
Beachten Sie, dass Sie den Swap nur als No-Throw-Methode verwenden müssen. Dies ist relativ einfach, wenn Sie STL-Objekte verwenden, da sie alle einen No-Throw-Swap definieren, genau wie Boost und alle guten Bibliotheken folge suite).

Wenn das schief geht, werden sie falsch mit dem Kopierkonstruktor arbeiten. An diesem Punkt haben Sie Ihr eigenes Objekt nicht verändert, während Sie das Konstruieren in ein temporäres kopieren. Somit bieten Sie eine gute Ausnahmesicherheit, da Ihr Objekt noch unverändert ist.

0

Sie wollen auch den Rückgabetyp ändern & const:

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

Weglassen konst Code wie den folgenden übersetzbar, während in Wirklichkeit ungültig sind sie machen:

(A = B) = C; 

Welche ist nicht entspricht dem folgenden: (was wahrscheinlich war)

A = B = C;