1

I do not know how to make constructors for an object with multiple raw pointers. I understand how to make it for one but do not understand multiple.

I have tried to write a new constructor during initialization, which then specifies what is accessed from the donor object.

I would like to know a way to make multiple constructors that extract different l values from one object depending on the order of initialization, however, I cannot find information about how to do this. I have some examples below.

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;}

I am at loss for understanding, I know I am missing something because this problem must be solvable. Please help me c++ master wherever you are.

3 Answers3

4

You shouldn't be using raw pointers at all here. There is no reason for it. It's just an invitation to make tons of errors.

Secondly, the syntax you have for initializers is very broken, that's not how the syntax works at all. I'll put in an example of what initializers should look like in here so you can see. You also misunderstand what new does. You don't need any of the assignments that you're doing. Not one of them.

Also, you've misspelled public as publuc. And the way you declare your constructor is not correct for declaring it as a class member.

You know, almost all the problems you have, the compiler should've given you at least vaguely sensible error messages about, and you shouldn't need us to fix them for you.

Here is an example class that uses some pointer members. Note that if you are using pointer members, especially as a C++ beginner, you are almost certainly doing something wrong. Bare pointers should be among the last things you learn about in C++, not the first:

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_;
};

This class does have one problem. If allocation of myint_ throws an exception, there will be a memory leak. This kind of thing is why you do not use raw pointers in C++, especially for member variables, and most especially if the thing they're going to be pointing at is allocated with new.

I deleted the copy constructor and assignment operator because they need special implementations for classes that contain raw pointers. I notice that you appear to have been trying to define your own copy constructor, but it's hard to tell because your constructor declaration is so very garbled.

Here is how this class should be written:

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

 private:
    bool mybool_;
    int myint_;
 };

If you absolutely must dynamically allocate things, do this:

 #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_;
 };

That class doesn't need a destructor to make sure it deletes the memory it allocates. It doesn't have a potential memory leak. It's all around a better class.

Omnifarious
  • 54,333
  • 19
  • 131
  • 194
0

Your copy constructor is all wrong. It needs to look like this instead:

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)))
   {
   }

   ...
};

You would also need to implement a destructor and a copy assignment operator, and in C++11 and later a move constructor and move assignment operator, per the Rule of 3/5/0, eg:

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;
   }
};

You can mitigate some of the risk of manually managing memory allocations by using smart pointers:

#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;
};

But really, there is no good reason to be using pointers at all in this situation. Get rid of the pointers altogether and let the compiler auto-generate appropriate constructors, destructor, and assignment operators that do all of the hard work of managing memory and copying values for you:

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

   // everything is auto-generated for you!
};
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

Thx you for the answers, this isn't homework though its late-night scribblings. I was really tired and trying to go ahead of what I have studied. Although on the bright side I haven't studied smart pointers yet so I feel less stupid, I just wanted to say thanks for being more constructive that I usually am over the internets.

  • 1
    Smart pointers are what you should use by default, not what you should use after you understand how regular pointers work. – Omnifarious Jun 21 '19 at 19:26