Какой беспорядок!
Всю программу очень трудно читать из-за выбора имен идентификаторов для начала:
#ifndef DELETE
#define DELETE(var) delete var, var = NULL
#endif
Я нахожу это очень уродливым.
При использовании классов это кажется очень бесполезным. Вы можете использовать его там, где переменные выходят из области видимости, но в деструкторе это пустая трата времени. Я думаю, что было бы лучше обернуть код в какой-нибудь умный указатель:
class Teste
{
private:
Teste *_Z;
public:
Teste()
~Teste() // Delete the _Z pointer.
Teste *Z();
void Z(Teste *value);
};
Ok. У вас есть указатель, который вы удаляете в деструкторе.
Это означает, что вы вступаете во владение указателем. Это означает, что применяется правило четырех (аналогично правилу трех, но применимо к правилам владения). Это означает, что вам нужно написать 4 метода, иначе сгенерированные компилятором версии испортят ваш код. Методы, которые вы должны написать:
A Normal (or default constructor)
A Copy constructor
An Assignment operator
A destructor.
Ваш код имеет только два из них. Вам нужно написать два других.
Или ваш объект не должен вступать во владение указателем RAW. то есть. используйте Smart Pointer.
Teste *_Z;
Это не разрешено.
Идентификаторы, начинающиеся с подчеркивания и заглавной буквы, зарезервированы.
Вы рискуете, что макрос ОС испортит ваш код. Прекратите использовать подчеркивание в качестве первого символа идентификаторов.
~Teste(){
if (_Z != NULL)
DELETE(_Z);
}
Это не нужно. Простое удаление _Z было бы хорошо.
_Z выходит из области видимости, потому что находится в деструкторе, поэтому нет необходимости устанавливать его в NULL.
Оператор удаления отлично обрабатывает указатели NULL.
~Test()
{ delete _Z;
}
Teste *Z(){
_Z = new Teste;
return _Z;
}
Что произойдет, если вы вызовете Z () несколько раз (PS, ставя * рядом с Z, а не рядом с Тестом, затрудняет чтение).
Каждый раз, когда вы вызываете Z (), переменной-члену _Z присваивается новое значение. Но что происходит со старым значением? По сути, вы это пропускаете. Также, возвращая указатель на объект, принадлежащий
внутри Teste вы даете кому-то возможность злоупотреблять объектом (удалить его и т. д.). Это не хорошо. Этот метод не указывает на явное право собственности.
Teste& Z()
{
delete _Z; // Destroy the old value
_Z = new Teste; // Allocate a new value.
return *_Z; // Return a reference. This indicates you are retaining ownership.
// Thus any user is not allowed to delete it.
// Also you should note in the docs that it is only valid
// until the next not const call on the object
}
void Z(Teste *value){
value->AnyNum = 100;
*_Z = *value;
}
Вы копируете содержимое вновь созданного объекта (который содержит указатель) в другой динамически созданный объект!
Что произойдет, если _Z не был выделен первым. Конструктор устанавливает его в NULL, поэтому нет гарантии, что он имеет допустимое значение.
Любой объект, который вы размещаете, вы также должны удалить. Но здесь значение динамически распределяется, передается в Z, но никогда не освобождается. Причина, по которой вам это сойдет с рук, заключается в том, что указатель
установлен в _Z и _Z удаляется при уничтожении его деструктора.
Teste *b = new Teste, *a;
Это действительно слышно читать. Не ленись, напиши это правильно.
Это считается плохим стилем, и вы никогда не пройдете ни один обзор кода с этим.
Teste* b = new Teste;
Teste* a; // Why not set it to NULL
a = b->Z();
Получение объекта ab для a. Но кто уничтожал объект а или б?
b->Z(new Teste);
После этого он становится слишком запутанным.