2010-05-18 4 views
0

У меня есть класс Person следующим образом:Конструкторы для C++ объекты

class Person { 
    char* name; 
    int age; 
}; 

Теперь мне нужно добавить два contructors. Один не принимает аргументов, который вставляет значения полей в динамически распределенные ресурсы. Вторые аргументы (char *, int), инициализированные списком инициализации. Последняя часть предназначена для определения деструктора, показывающего информацию об уничтожении объектов и освобождении динамически распределенных ресурсов. Как выполнить эту задачу?

Вот что у меня уже есть:

class Person { 
    char* name; 
    int age; 
public: 
    Person(){ 
     this->name = new *char; 
     this->age = new int; 
    } 

    Person(char* c, int i){ 
    } 
}; 

ответ

3

В конструктор по умолчанию, выделение массив символов должен включать его нужный размер, например

this->name = new char[32]; 

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

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

В деструкторе, вы должны освободить динамически выделенные ресурсы - убедитесь, что использовать delete[] когда, и только тогда, когда освобождения памяти выделяется new[]:

~Person(){ 
    std::cout << "Destroying resources" << std::endl; 
    delete[] name; 
    delete age; 
} 

Update: Я пропустил этот: если вы хотите выделить age динамически, вы должны объявить его как int* age.

Я предполагаю, что целью этого упражнения является практика динамического распределения/освобождения; в этом контексте это прекрасно. Однако, в целом, не рекомендуется динамически распределять int s, а вместо char* вы должны почти всегда использовать std::string, который автоматически и безопасно обрабатывает выделение памяти.

+0

http://paste.pocoo.org/show/215191/, но он дает мне ошибку «недопустимое преобразование из' междунар * „в' междунар“» в возрасте. – sasquatch

+0

@sasquatch, см. Мое обновление. –

0

Вы также можете выделить только память, необходимую для копирования имени, если вы хотите его установить. Кроме того, не забудьте освободить выделенный буфер, когда объект будет уничтожен!

class Person { 
    char* name; 
    int age; 
public: 
    Person(){ 
     this->name = NULL; 
     this->age = 0; // no need to allocate memory for basic types 
    } 

    ~Person(){ 
     delete [] name; 
    } 

    set(char* c, int i){ 
     this->age = i; 

     // copy name if input pointer name is valid 
     if (c != NULL){ 
      // if memory have already been allocated : delete first 
      if (this->name != NULL){ 
       delete [] name; 
       name = NULL; 
      } 
      // allocate memory : 1 more char for the trailing '\0' 
      this->name = new char[strlen(c)+1]; 
      // copy string 
      strcpy(this->name,c); 
     } 
    } 
}; 

Редактировать и ответ на замечания:

  • упрощена деструктор следующее предложение Конрада Рудольфа
  • Я, как правило, всегда устанавливать нераспределенные и освобождаться указатели на NULL, чтобы избежать выбора места случайных памяти, когда указатель не используется правильно, и нераспределенные указатели также легче обнаружить в debbuger.
  • Я не обращал внимания, что второй метод был конструктором, я думал, что это сеттер ... изменил его.
+1

Деструктор может быть сведен к единственной команде 'delete [] name;'. Проверка на 'NULL' не нужна, как и задание. –

+0

У последнего конструктора также есть серьезные проблемы: 'this-> name' будет неинициализирован в этой точке, что означает, что вы можете легко удалить указатель мусора. И, в конце концов, 'this-> name' не может указывать на какую-либо выделенную память, потому что конструктор вызывается, когда объект сначала возникает. - И еще одна проблема, если 'c' - NULL, тогда' this-> name' останется неинициализированным. – visitor

1

Учитывая ваше заявление, вы не может инициализировать age динамически выделенную память, так как age не является указателем.

Вы можете, конечно, изменить тип age на номер int*. Но я бы этого не сделал, это нецелесообразно.Неясно, действительно ли задание запрашивает динамическое распределение (и если да - , почему?).

Для name, с другой стороны, вы можете продолжить, как указано @ Péter. Но еще раз, это не очень хорошее решение в большинстве случаев, потому что C++ предлагает класс string, который прекрасно переносит управление строками в класс. Если это разрешено, используйте string вместо char* и динамическое распределение памяти.

2

Используя класс C++ string вы можете забыть о ручных (и опасных) управлениях памятью:

class Person { 
    public: 
     Person() : name_(""), age_(0) { } 
     Person (const std::string& name, int age) : name_(name), age_(age) { } 
    // There is no need for the destructor as the memory is managed by the string class. 
}; 

Также see this link по той причине, почему вы должны всегда использовать список инициализации вместо заданий в конструкторе.

0

Я рекомендую использовать строковый класс вместо char *.

Что-то вроде этого:

class Person 
{ 
public: 
    Person() : name(""), age(0) {} 
    Person(const string& n, int a) : name(n), age(a) {} 

    // whatever here. 

    ~Person() {} // do nothing 

private: 
    string name; 
    int age; 
}; 
Смежные вопросы