views:

738

answers:

7

Hi everybody. I was wondering if you guys could help me.

Here are my .h:

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

and my main:

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

I want to do the operator= function. Can anyone help me? Notice the const member on Doctor.

********EDIT:***** My main problem is that I want another class to have an attribute which is a Doctor like a Pacient has a Doctor. But I want to be able to change my Doctor. Like i am seeing doctor A but I want to see Doctor B. That would be done using a setDoctor function in my other class (Pacient). If it was me doing the code I would say something like this:

class Patient{
    Doctor &d;
};

and then change the pointer. However I am using a base code made by one of the teachers and it has the class defined like:

class Patient{
     Doctor d;
}

But I think this is impossible to do because with a setDoctor() in the Patient class I would either make a copy or alter the varable itself. The first doesn't make any difference and the second is impossible due to the const. Am I right?

A: 

Since your name is const, the only way to "change" it is through the constructor. If you want to use the = operator, you need to "unconst" the string.

.. if you don't want to "unconst" the string, you could get somewhat equal behaviour by creating a copy-constructor:

Doctor(const &Doctor d);

.. and implement it:

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
}
cwap
David Rodríguez - dribeas
Aaah yes, I knew I forgot something :) Ill edit my answer
cwap
to add to dribeas' correction, you also can't change the string within the constructor. the string is const. the only one that can change the string is string's constructor itself.
Johannes Schaub - litb
+2  A: 

The declaration is Doctor &operator=(const Doctor &other); (i.e., remove the Doctor::)

from there you'd need to use const_cast<> to remove the const-ness of the member variable to make it work. Note that only heartbreak lies in the path you've chosen.

I'd recommend removing const from the member declaration and instead making member functions const as necessary to show that they won't affect the object. (For example if you have an accessor member function you could declare that const: string getName() const { return m_name; })

Indeed.. const_cast<> is made by the devil :) That's why I didn't add it to my answer.
cwap
+7  A: 

You are almost there. Few noteworthy points:

  • The name should not be const qualified. A const cannot be modified, which is exactly what we want in the assignment operator.

  • The C++ keyword is class and not Class as your code has it (it'll give you compile errors)

  • As Michael Burr notes: "It should be noted though that if the class simply contains other classes that already properly support assignment (as in this case with a simple string member), the implicit, compiler-generated operator=() will work just fine." Here, in your case, the only member string has a proper op=. So explicitly defining is redundant.

  • Meeh's solution is almost there. The only thing it doesn't talk about is self-assignment. Read FAQ 12.

  • Assignment is one the Big Three member functions FAQ 27.10. Look it up. It says, requirement to implement either one of copy ctor, op= or the dtor usually implies that you'd need to implement the other two as well.

The corrected code sample should be something like this:

class Doctor {
  string name;
  public:
    Doctor& operator=(Doctor const& o) { 
         if (&o != this) name = o.name;
         return *this;
    }
  // ...
};
dirkgently
It should be noted though that if the class simply contains other classes that already properly support assignment (as in this case with a simple string member), the implicit, compiler-generated operator=() will work just fine.
Michael Burr
@Michael: Yep, I ought to have added this. I'll edit my post.
dirkgently
@Michael: The const problem also aplies if we have "Doctor d1 = NULL; Doctor d2 = Doctor(); d1 = d2;" ?
Rui Carneiro
+1  A: 

I am pretty sure it is a nicely restated homework problem :)

+1  A: 

As many have said earlier, the member is 'const' indicates that it has to be initialized during its creation and it is not supposed to change. If at all you have to write an assignment operator for such cases and you cannot skip the assignment of that member variable, then make it 'mutable'.

Remember; from the C++ standard, "casting away constness of an originally declared const variable is undefined behaviour."

HTH, Abhay

Abhay
+2  A: 

The standard way to define the assignment constructor correctly so that it is exception safe is to define it in terms of the copy constructor.

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

By doing it like this makes it exception safe.
Note you just need to make the swap a no-throw method, this is relatively simple if you are using STL objects as they all define a no-throw swap just for this situation as does boost and all good libraries (so you should follow suite).

If this going wrong they will go wrong in using the copy constructor. At this point you have not modified your own object as you are copy constructing into a temporary. Thus you are providing good exception safety as your object is still un-changed.

Martin York
A: 

You also want to change the return type to const&:

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

Omitting const will make code such as the following compilable while in reality they are invalid:

(A = B) = C;

Which is not equivalent to the following: (which is what was probably intended)

A = B = C;
Ash