2012-03-12 4 views
0

Я работаю с классом, который в основном работает нормально, но я выполняю некоторые функции, которые могут иметь рекурсивную функцию, возвращают указатель типа класса в качестве элемента управления, и поэтому он может быть назначая NULL указатель на мой объект класса так долго короткий рассказ:Оператор присваивания C++ Назначение NULL

Thing& Thing::operator=(Thing * _other){ 
    if (_other == NULL){ 
     *this = NULL;  // compiler throws here 
     return *this;  
    } 
    // does other assignment work 
    return *this; 
} 

мой компилятор VS2010 бросает, что this не является I-значение. так как мне установить значение NULL, или даже можно установить элемент в NULL изнутри?

EDIT: модифицировано this до *this, хотя по какой-то причине программа прерывается бесконечными вызовами оператора присваивания. не знаю, что происходит

+2

'* this = NULL' снова вызывает ваш оператор, который переходит в if, вызывающий ваш оператор, и т. Д. Если вы хотите написать оператор присваивания копий, он должен принимать аргумент с помощью ссылки const или значения (см. копия и смена идиомы). –

+0

Почему вы не используете конструктор копирования? – Alex

+0

@Alex аналогичный должен был быть сделан в конструкторе копирования. потому что большинство конструкторов копий просто копируют объект arg, и если вы пытаетесь скопировать NULL-данные, большинство отладчиков/exectables сбой или должны. – gardian06

ответ

1

каких переменные-членов Класс? , если вы хотите показать, что объект каким-то образом не имеет значения или не инициализирован, вам лучше назначить files 0 (для целых чисел) и null (для указателей) и т. Д. Вместо назначения «this», который является постоянным.

+0

Это требует изменения тестов, но это также кажется одним из самых прямых и не заставляет меня менять кучу моей реализации. – gardian06

+0

Может быть, лучше править член function 'void Thing :: initializeNull() {}' и выполняет эти назначения в нем и вызывается, когда вам нужно, и в конструкторе по умолчанию Thing. – rene

2

Вы не можете прямо установить значение в указатель this. Следовательно,

this = NULL; 

является семантически и синтаксически неправильным.

Вы можете использовать исключения, чтобы проверить, соответствует ли _other значение NULL. Например:

class null_object_exception : public virtual exception {}; 
... 
if (_other == NULL) throw null_object_exception(); 

Чтобы выполнить NULL задание:

Thing the_thing, other_thing; 
try { the_thing = &other_thing; } 
catch(const null_object_exception& e) { the_thing = NULL; } 
+0

, поэтому то как выполнить присвоение «NULL», если назначаемая вещь является «NULL» – gardian06

+0

Вы можете сделать это в инструкции 'catch'. – ApprenticeHacker

+0

@ gardian06 проверить изменение. Надеюсь, что решает вашу проблему. – ApprenticeHacker

1

Вы НЕ присваиваемое this.

Кроме того, вы должны принять ваши аргументы const ссылки, так Thing& operator= (const Thing& other)

Там отличный SO вопрос в C++ - чаво тег о перегрузке операторов, вы можете найти его here

+2

'this' не' const', он дает значение r. –

+0

@CatPlusPlus после выполнения некоторых проверок это const * для текущего объекта и может быть назначен, произнося '* this', хотя он просто рассматривает его как другой объект – gardian06

+1

@ gardian06: Это не указатель const, это exp который дает указатель rvalue. Это может быть указатель на const, но это зависит от константы объекта. Выделение его не дает другого указателя, оно дает ссылку (возможно, const) на объект - вы никогда не изменяете указатель 'this', потому что это невозможно. –

1

Короткий ответ, нет, вы не можете назначить this в C++.

Долгий ответ; для того, чтобы ваш оператор присваивания даже был вызван, вы должны иметь такую ​​конструкцию;

MyObject a; 
a = NULL; // can change the content of `a` but not which object the name `a` refers to. 

Если вы думаете об этой конструкции;

MyObject *a; 
a = NULL; 

ваш оператор присваивания не будет даже назвать, так как он является оператором на объекта, а не указатель. Присвоение указателю a будет работать без указания оператора присваивания.

+0

будет «MyObject a = NULL» даже назвать Thing :: operator = (Thing * _other)? NULL не относится к типу Thing *, так почему бы вызвать эту перегрузку? –

+0

@KJTsanaktsidis Было бы разумно, что это не так, но да. Если у вас несколько перегрузок с помощью указателей, NULL вызовет ошибку компиляции из-за неоднозначной перегрузки. –

2

Вы пытаетесь написать класс с «нулевым» значением. Рассмотрим состояние «null» как одно из состояний, в котором экземпляр Thing может находиться внутри, и не свертывать его с помощью семантики указателя.

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

class Thing 
{ 
private: 
    bool m_null; 

public: 
    void setnull() { m_null = true; } 
    bool isnull() const { return m_null; } 

    Thing() : m_null(true) {} 

    ... // rest of class 
}; 

И теперь оператор присваивания по умолчанию работает нормально.

Смежные вопросы