Конструкторы C ++ с несколькими необработанными указателями - PullRequest
1 голос
/ 20 июня 2019

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

Я попытался написать новый конструктор во время инициализации, который затем указывает, к чему обращается объект-донор.

Я хотел бы знать способ создания нескольких конструкторов, которые извлекают разные значения l из одного объекта в зависимости от порядка инициализации, однако я не могу найти информацию о том, как это сделать. У меня есть несколько примеров ниже.

class Movie {
   publuc:
   std::string *movie_name;
   std::string *age_rating; 
   int *view_count;
   int *rating;
Movie::Movie(const Movie &source , const Movie &source , const Movie &source , const Movie &source)
    : {movie_name = new string;
      *movie_name source;},
      {age_rating = new string;
      *age_rating source;}, 
      {view_count = new int;
      *view_count source;},
      {source.rating = new int;
      *source.rating source;}

Я в недоумении для понимания, я знаю, что что-то упустил, потому что эта проблема должна быть решаемой. Пожалуйста, помогите мне мастер C ++, где вы находитесь.

Ответы [ 3 ]

4 голосов
/ 20 июня 2019

Вы не должны здесь использовать необработанные указатели. Там нет причин для этого. Это просто приглашение сделать кучу ошибок.

Во-вторых, синтаксис, который вы используете для инициализаторов, очень нарушен, синтаксис работает совсем не так. Я приведу пример того, как инициализаторы должны выглядеть здесь, чтобы вы могли видеть. Вы также неправильно понимаете, что делает new. Вам не нужно никаких заданий, которые вы делаете. Ни один из них.

Кроме того, вы ошиблись public как publuc. И способ, которым вы объявляете ваш конструктор, не подходит для объявления его как члена класса.

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

Вот пример класса, который использует некоторые члены-указатели. Обратите внимание, что если вы используете члены-указатели, особенно как начинающий C ++, вы почти наверняка делаете что-то не так. Голые указатели должны быть среди последних вещей, о которых вы узнаете в C ++, а не первыми:

class IHaveSomePointers {
 public:
   IHaveSomePointers(bool const &mybool, int const &myint)
      : mybool_{new bool(mybool)}, myint_{new int(myint)}
   { }
   ~IHaveSomePointers() {
       delete mybool_;
       delete myint_;
   }
   IHaveSomePointers(IHaveSomePointers const &) = delete;
   void operator =(IHaveSomePointers const &) = delete;

 private:
   bool *mybool_;
   int *myint_;
};

У этого класса есть одна проблема. Если выделение myint_ вызывает исключение, произойдет утечка памяти. Именно из-за этого вы не используете необработанные указатели в C ++, особенно для переменных-членов, и особенно, если объект, на который они будут указывать, выделен с помощью new.

Я удалил конструктор копирования и оператор присваивания, потому что им нужны специальные реализации для классов, которые содержат необработанные указатели. Я заметил, что вы, кажется, пытались определить свой собственный конструктор копирования, но это трудно сказать, потому что ваше объявление конструктора очень искажено.

Вот как этот класс должен быть написан:

class IDontHavePointersBecauseThatsBad {
 public:
    IDontHavePointersBecauseThatsBad(bool const &mybool, int const &myint)
       : mybool_{mybool}, myint_{myint}
    { }

 private:
    bool mybool_;
    int myint_;
 };

Если вам абсолютно необходимо динамически распределять объекты, сделайте следующее:

 #include <memory>

 class ForSomeBizarreReasonIDyanmicallyAllocate {
  public:
    ForSomeBizarreReasonIDynamicallyAllocate(bool const &mybool, int const &myint)
        : mybool_{::std::make_unique<bool>(mybool)},
          myint_{::std::make_unique<int>(myint)}
    { }

  private:
    ::std::unique_ptr<bool> mybool_;
    ::std::unique_ptr<int> myint_;
 };

Этому классу не нужен деструктор, чтобы убедиться, что он удаляет память, которую он выделяет. У него нет потенциальной утечки памяти. Все вокруг лучшего класса.

0 голосов
/ 20 июня 2019

Спасибо за ответы, это не домашнее задание, а ночные писанины. Я очень устал и пытался идти впереди того, что я изучал. Хотя, с другой стороны, я еще не изучал умные указатели, поэтому чувствую себя менее глупо, я просто хотел поблагодарить за то, что я более конструктивен, чем обычно, из интернета.

0 голосов
/ 20 июня 2019

Ваш конструктор копирования неверен. Это должно выглядеть так:

class Movie {
public:
   std::string *movie_name;
   std::string *age_rating; 
   int *view_count;
   int *rating;

   Movie(const Movie &source) :
      movie_name(new string(*(source.movie_name))),
      age_rating(new string(*(source.age_rating))),
      view_count(new int(*(source.view_count))),
      rating(new int(*(source.rating)))
   {
   }

   ...
};

Вам также потребуется реализовать деструктор и оператор присваивания копии, а в C ++ 11 и более поздних версиях конструктор перемещения и оператор присваивания перемещения в соответствии с правилом 3/5/0 , например :

class Movie {
public:
   std::string *movie_name;
   std::string *age_rating; 
   int *view_count;
   int *rating;

   Movie() :
      movie_name(new string),
      age_rating(new string),
      view_count(new int(0)),
      rating(new int(0))
   {
   }

   Movie(const Movie &source) :
      movie_name(new string(*(source.movie_name))),
      age_rating(new string(*(source.age_rating))),
      view_count(new int(*(source.view_count))),
      rating(new int(*(source.rating)))
   {
   }

   Movie(Movie &&source) :
      movie_name(source.movie_name),
      age_rating(source.age_rating),
      view_count(source.view_count),
      rating(source.rating)
   {
      source.movie_name = nullptr;
      source.age_rating = nullptr;
      source.view_count = nullptr;
      source.rating = nullptr;
   }

   ~Movie()
   {
      delete movie_name;
      delete age_rating;
      delete view_count;
      delete rating;
   }

   Movie& operator=(const Movie &source)
   {
      if (&source != this)
      {
         *movie_name = *(source.movie_name);
         *age_rating = *(source.age_rating);
         *view_count = *(source.view_count);
         *rating = *(source.rating);
      }
      return *this;
   }

   Movie& operator=(Movie &&source)
   {
      Movie temp(std::move(source));
      std::swap(movie_name, temp.movie_name);
      std::swap(age_rating, temp.age_rating);
      std::swap(view_count, temp.view_count);
      std::swap(rating, temp.rating);
      return *this;
   }
};

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

#include <memory>

class Movie {
public:
   std::unique_ptr<std::string> movie_name(new string);
   std::unique_ptr<std::string> age_rating(new string); 
   std::unique_ptr<int> view_count(new int(0));
   std::unique_ptr<int> rating(new int(0));

   Movie() = default;

   Movie(const Movie &source) :
      movie_name(new string(*(source.movie_name))),
      age_rating(new string(*(source.age_rating))),
      view_count(new int(*(source.view_count))),
      rating(new int(*(source.rating)))
   {
   }

   Movie(Movie &&source) = default;

   ~Movie() = default;

   Movie& operator=(const Movie &source)
   {
      if (&source != this)
      {
         *movie_name = *(source.movie_name);
         *age_rating = *(source.age_rating);
         *view_count = *(source.view_count);
         *rating = *(source.rating);
      }
      return *this;
   }

   Movie& operator=(Movie &&source) = default;
};

Но на самом деле, нет веской причины вообще использовать указатели в этой ситуации. Полностью избавьтесь от указателей и позвольте компилятору автоматически генерировать соответствующие конструкторы, деструкторы и операторы присваивания, которые выполняют всю тяжелую работу по управлению памятью и копированию значений для вас:

class Movie {
public:
   std::string movie_name;
   std::string age_rating; 
   int view_count = 0;
   int rating = 0;

   // everything is auto-generated for you!
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...