서형박 Ответов: 1

<C++> У меня есть вопрос об инициализации и изменении переменных-членов класса


Этот код является примером для книги, которую я изучаю. Мне интересно, почему авторы определили конструктор, справляясь с аргументами, передаваемыми через динамическое распределение, оставляя удобство функции SetPersonInfo?

Что я уже пробовал:

class Person
{
	char * name;
	int age;
public:
	Person(const char * myname, int myage)
	{
		int len = strlen(myname) + 1;
		name = new char[len];
		strcpy(name, myname);
		age = myage;
	}
	Person()
	{
		name = NULL:
		age = 0;
	}
	void SetPersonInfo(const char * myname, int myage)
	{
		name = myname;
		age = myage;
	}
	void ShowPersonInfo() const
	{
		cout << name << ' ' << age << endl;
	}
	~Person()
	{
		delete[]name;
	}
};

1 Ответов

Рейтинг:
0

Rick York

Это выглядит как плохой дизайн для меня. Метод SetPersonInfo просто назначает переменные, что нормально. Проблема в том, что деструктор всегда удаляет массив. Если бы имя было литеральной строкой или другими не выделенными данными, то это вызвало бы исключение. По-видимому, это предполагает, что переданное имя также было выделено. Я думаю, что конструктор, принимающий аргументы, должен быть реализован как метод SetPersonInfo, чтобы он всегда делал копию, и это означало бы, что деструктор всегда безопасен. Вот что я считаю лучшей реализацией.

class Person
{
	char * name;
	int age;
public:
	Person()
	{
		name = NULL:
		age = 0;
	}
	Person(const char * myname, int myage)
	{
		SetInfo( myname, myage );
	}
	void SetInfo(const char * myname, int myage)
	{
		name = strdup( myname );
		age = myage;
	}
	void ShowInfo() const
	{
		cout << name << ' ' << age << endl;
	}
	~Person()
	{
		free( name );
	}
};
Да, я знаю, что он использует текстовые строки в стиле C, но оригинал тоже использовал свой вызов strcpy. Лучшим способом было бы использовать строку std::, и тогда не было бы необходимости в выделении или освобождении. Класс std::string управляет всем этим сам. Вот что такое реализация :
class Person
{
	std::string name;
	int age;
public:
	Person()
	{
		age = 0;
	}
	Person(const char * myname, int myage)
	{
		SetInfo( myname, myage );
	}
	void SetInfo(const char * myname, int myage)
	{
		name = myname;
		age = myage;
	}
	void ShowInfo() const
	{
		cout << name << ' ' << age << endl;
	}
	~Person()
	{
	}
};
Как видите, все немного проще.


서형박

Большое вам спасибо за Ваш полезный ответ!. Еще один вопрос заключается в том, что вместо использования strdup параметр myname должен передавать адрес переданной строки в name как есть? например, 'name = myname'

Rick York

Во втором примере name-это строка std:, и ее оператор присваивания принимает аргумент const char * и делает его копию. Strdup делает по существу то же самое в первом примере, за исключением того, что это простая версия C.