Почему этот конструктор написан как есть?

Наш профессор разместил в Интернете пользовательский файл шаблона «String» и недавно попросил нас заполнить указанные ниже функции. Мой вопрос, чтобы попытаться понять это, почему три верхних конструктора имеют Text = NULL; и под ним, this = source;, какая-то другая форма этого. Я чувствую, что каждый должен сказать Text = the_input_parameter,

Большое спасибо, вот код:

class String
{
public:
// Default constructor
String()
{
Text = NULL;
}
String(const String& source)
{
Text = NULL;
// Call the assignment operator to perform deep copy
*this = source;
}
String(const char* text)
{
Text = NULL;
// Call the assignment operator to perform deep copy

*this = text;

}
~String()
{
delete[] Text;
}

// Assignment operator to perform deep copy
String& operator = (const char* text)
{
// Ddispose of old Text
delete[] Text;

// +1 accounts for NULL-terminator
int trueLength = GetLength(text) + 1;

// Dynamically allocate characters on heap
Text = new char[trueLength];

// Copy all characters from source to Text; +1 accounts for NULL-terminator
for ( int i = 0; i < trueLength; i++ )
Text[i] = text[i];

return *this;
}

// Returns a reference to a single character from this String
char& operator [] (int index) const
{
int length = GetLength();

// Check for valid index
if ( (index < 0) || (index > length) )
{
stringstream error;
error << "operator[] - index " << index << " is out of bounds (0.." << (length - 1) << ")";
throw String(error.str().c_str());
}

return Text[index];
}
private:
// The encapsulated C-string
char* Text;
};

0

Решение

Это просто способ выделить общий код во вспомогательную функцию. В этом случае, operator=() действует как вспомогательная функция. Его функция заключается в освобождении текущей строки (в этом случае NULL) и выполнить глубокую копию правой части.

Я чувствую, что каждый должен сказать Text = the_input_parameter,

За String(const String& source) это не скомпилируется с source не тот тип

За String(const char* text) это не было бы правильно, так как это просто назначило бы указатель вместо выполнения глубокой копии.

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

1

Другие решения

Почему вы не должны реализовывать конструкторы с точки зрения назначения:

  • Это становится довольно неприятным в производных классах. Думаю об этом.
  • Трудно сделать исключение безопасным.
  • Кроме того, загрузка неэффективна (требует построения по умолчанию, а затем присваивания).

Таким образом, ответ на вопрос, почему это сделано в вашем примере кода, возможно, заключается в том, что ваш профессор не слишком разбирается в программировании на C ++.

Иначе трудно сказать: просто не имеет никакого смысла делать это.


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

Это просто, исключения безопасны и в целом эффективны, и выглядят так:

class Foo
{
public:
void swap_with( Foo& other ) throw()
{
// No-throwing swap here.
}

void operator=( Foo other )
{
other.swap_with( *this );
}
};

да, это все.

Варианты включают в себя именование swapper просто swapи позволяя оператору присваивания возвращать ссылку, а некоторые предпочитают передавать аргумент по ссылке, а затем делать копию (используя конструкцию копирования).

6

Класс управляет памятью, поэтому деструктор освобождает ее, а оператор присваивания выделяет новые для новых данных и освобождает старые (должно быть в таком порядке).

Тогда объяснение начального присваивания становится ясным: вам нужно инициализировать поле члена с правильным значением, так как в противном случае оно будет содержать мусор (некоторый указатель куда-то), который код будет пытаться использовать и освободить.

Хотя это не видно из кода, может быть также назначение для const String& и введите оператор приведения operator const char *() const,

0