Оператор = Перегрузка с константной переменной в C ++ - PullRequest
4 голосов
/ 13 апреля 2009

Мне было интересно, если вы, ребята, могли бы помочь мне.

Вот мой .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 =. Может кто-нибудь мне помочь? Обратите внимание на постоянного члена на Докторе.

************ EDIT: ********* Моя главная проблема в том, что я хочу, чтобы другой класс имел атрибут «Доктор», как у «Пациента» есть «Доктор». Но я хочу сменить доктора. Как будто я встречаюсь с доктором А, но я хочу видеть доктора Б. Это можно сделать с помощью функции setDoctor в моем другом классе (Pacient). Если бы я делал код, я бы сказал что-то вроде этого:

class Patient{
    Doctor &d;
};

и затем измените указатель. Однако я использую базовый код, созданный одним из учителей, и его класс определен так:

class Patient{
     Doctor d;
}

Но я думаю, что это невозможно сделать, потому что с помощью setDoctor () в классе Patient я бы либо сделал копию, либо изменил сам varable. Первое не имеет никакого значения, а второе невозможно из-за постоянства. Я прав?

Ответы [ 6 ]

7 голосов
/ 13 апреля 2009

Вы почти у цели. Несколько заслуживающих внимания очков:

  • Имя не должно быть const квалифицированным. const не может быть изменено, что именно то, что мы хотим в операторе присваивания.

  • Ключевое слово C ++ - class, а не Class, поскольку оно есть в вашем коде (оно даст вам ошибки компиляции)

  • Как отмечает Майкл Барр: «Следует отметить, что, если класс просто содержит другие классы, которые уже должным образом поддерживают присваивание (как в этом случае с простым строковым членом), неявный оператор, сгенерированный компилятором = () будет работать просто отлично. " Здесь, в вашем случае, единственный член string имеет правильный op=. Таким образом, явное определение является избыточным.

  • Решение Миха уже почти у цели. Единственное, о чем он не говорит, - это о себе. Читать FAQ 12 .

  • Назначение - одна из функций-членов Большой тройки FAQ 27.10 . Поищи это. В нем говорится, что требование для реализации одного из копий ctor, op = или dtor обычно подразумевает, что вам нужно будет реализовать и другие два.

Исправленный пример кода должен выглядеть примерно так:

class Doctor {
  string name;
  public:
    Doctor& operator=(Doctor const& o) { 
         if (&o != this) name = o.name;
         return *this;
    }
  // ...
};
3 голосов
/ 13 апреля 2009

Стандартный способ правильно определить конструктор присваивания, чтобы исключить его исключительную ситуацию, - определить его в терминах конструктора копирования.

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, поскольку все они определяют своп без бросков только для этой ситуации, как Boost и все хорошие библиотеки (поэтому вы должны следовать комплекту ).

Если это не так, они будут ошибаться при использовании конструктора копирования. На данный момент вы не изменили свой собственный объект, поскольку вы копируете конструкцию во временный. Таким образом, вы обеспечиваете хорошую безопасность исключений, поскольку ваш объект все еще остается неизменным.

2 голосов
/ 13 апреля 2009

Декларация Doctor &operator=(const Doctor &other); (т.е. удалить Доктора ::)

оттуда вам нужно будет использовать const_cast <>, чтобы удалить постоянство переменной-члена, чтобы она работала. Обратите внимание, что на выбранном вами пути лежит только горе.

Я бы рекомендовал удалить const из объявления члена и вместо этого сделать функции-члены const по мере необходимости, чтобы показать, что они не будут влиять на объект. (Например, если у вас есть функция-член accessor, вы можете объявить это const: string getName() const { return m_name; })

1 голос
/ 13 апреля 2009

Как уже говорили многие ранее, элемент const указывает, что он должен быть инициализирован во время своего создания и не должен изменяться. Если вам вообще нужно написать оператор присваивания для таких случаев и вы не можете пропустить присваивание этой переменной-члена, то сделайте ее 'изменяемой'.

Помните; по стандарту C ++ «отбрасывание константы первоначально объявленной константной переменной - неопределенное поведение».

НТН, Абхай

0 голосов
/ 13 апреля 2009

Вы также хотите изменить тип возвращаемого значения на const &:

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

Пропуск const сделает код, такой как следующий, компилируемым, в то время как в действительности они недопустимы:

(A = B) = C;

Что не эквивалентно следующему: (что, вероятно, и предполагалось)

A = B = C;
0 голосов
/ 13 апреля 2009

Поскольку ваше имя const, единственный способ «изменить» его - через конструктор. Если вы хотите использовать оператор =, вам нужно «восстановить» строку.

.. если вы не хотите "отвязывать" строку, вы можете получить несколько одинаковое поведение, создав конструктор копирования:

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