Наш профессор разместил в Интернете пользовательский файл шаблона «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;
};
Это просто способ выделить общий код во вспомогательную функцию. В этом случае, operator=()
действует как вспомогательная функция. Его функция заключается в освобождении текущей строки (в этом случае NULL
) и выполнить глубокую копию правой части.
Я чувствую, что каждый должен сказать
Text = the_input_parameter
,
За String(const String& source)
это не скомпилируется с source
не тот тип
За String(const char* text)
это не было бы правильно, так как это просто назначило бы указатель вместо выполнения глубокой копии.
Выше предполагается, что вы показываете нам только часть класса, и что реальный класс определяет соответствующий оператор присваивания и деструктор. Если это не так, вам нужен новый профессор.
Почему вы не должны реализовывать конструкторы с точки зрения назначения:
Таким образом, ответ на вопрос, почему это сделано в вашем примере кода, возможно, заключается в том, что ваш профессор не слишком разбирается в программировании на C ++.
Иначе трудно сказать: просто не имеет никакого смысла делать это.
Однако, если пойти другим путем, а именно реализовать назначение копирования с точки зрения создания копии, это очень распространено и называется идиома копирования и обмена.
Это просто, исключения безопасны и в целом эффективны, и выглядят так:
class Foo
{
public:
void swap_with( Foo& other ) throw()
{
// No-throwing swap here.
}
void operator=( Foo other )
{
other.swap_with( *this );
}
};
да, это все.
Варианты включают в себя именование swapper просто swap
и позволяя оператору присваивания возвращать ссылку, а некоторые предпочитают передавать аргумент по ссылке, а затем делать копию (используя конструкцию копирования).
Класс управляет памятью, поэтому деструктор освобождает ее, а оператор присваивания выделяет новые для новых данных и освобождает старые (должно быть в таком порядке).
Тогда объяснение начального присваивания становится ясным: вам нужно инициализировать поле члена с правильным значением, так как в противном случае оно будет содержать мусор (некоторый указатель куда-то), который код будет пытаться использовать и освободить.
Хотя это не видно из кода, может быть также назначение для const String&
и введите оператор приведения operator const char *() const
,