user3443063
user3443063

Reputation: 1615

C++ constructor initialisation list

I have a class, Auteur, with the following constructor, copy constructor and destructor:

class Auteur
{
    public:
        Auteur(string nom, bool prime=false) : nom_(nom), prime_(prime)  {}

        Auteur(const Auteur& a)=delete;

        ~Auteur()   {}

    private:
        string nom_;
        bool prime_;
};

Now I want to create a new class that uses the class Autheur along with two other parameters. I tried like this, but it didn’t work. How can I write the correct constructor for Oeuvre?

class Oeuvre
{
    public:
        Oeuvre(string titre, Auteur const& auteur_, string langue)
         : titre_(titre), auteur(nom, prime), langue_(langue)

        Oeuvre(Oeuvre const& o) = delete;
         : titre_(o.titre_), auteur_(o.auteur_), langue_(o.langue_)        {}

        ~Oeuvre()   {}

        public:
            Auteur auteur_;
            Auteur auteur;
            string langue_;
            string titre_;
    };

I don`t want to change the copy constructor. But I still have a problem when I try to create a new Oeuvre in main:

int main()
{
  Auteur a1("Victor Hugo"),
         a3("Raymond Queneau", true);

  Oeuvre o1("Les Misérables" , a1, "français"),
         o2("L'Homme qui rit", a1, "français");

  return 0;
}

Since the program needs four parameters for the constructor (Oeuvre) and in the main() I create some objects with only three parameters I get an error. (I don’t want to change the main().)

What can I do about this?

Upvotes: 1

Views: 176

Answers (2)

ChuckAtkins
ChuckAtkins

Reputation: 51

A couple of things:

  1. Use const& for string parameters. They're going to get copied anyways into the members so no need for the extra copy just to pass them in to the functions.
  2. Deleting the copy constructor for Auteur is fine; it's simply ensuring that the object cannot be passed by value and must be passed by reverence whenever it's used.
  3. It doesn't make sense to delete the copy constructor for Oeuvre and also give it an implementation. Either have one or don't but you can't have both.
  4. If you don't need a separate copy of Auteur but only want to reference an existing object, keep it as a constant reference member instead.
  5. No need to define an empty destructor. You will automatically get the default.

Given those things:

#include <string>

class Auteur
{   
public:   
  Auteur(std::string const& nom,  bool prime=false)          
  : nom_(nom), prime_(prime)  
  {}

  Auteur(Auteur const&) = delete;         

private:
  std::string nom_;
  bool prime_;
};

.

class Oeuvre
{   
public:   
  Oeuvre(std::string const& titre, std::string const& langue, Auteur& auteur)
  : titre_(titre), langue_(langue), auteur_(auteur)
  { }

  Oeuvre(Oeuvre const&) delete;

public:
  const Auteur &auteur_;
  std::string langue_;
  std::string titre_;
};

.

int main()
{
  Auteur a1("Victor Hugo"),
         a3("Raymond Queneau", true);

  Oeuvre o1("Les Misérables"  , "français", a1),
         o2("L'Homme qui rit" , "français", a1);

  return 0;
}

Upvotes: 2

user2033018
user2033018

Reputation:

Well, you deleted the copy constructor of class Auteur, which means that a construction like

Auteur a1("Victor Hugo");
Auteur a2(a1);

is now illegal, since a2 will be copy-constructed from a1.

The initializer list of a class' constructor isn't different from this. You're constructing o1 with several parameters, one of which happens to be a1. Now well, within Oeuvre's constructor, you're initializing (i.e. constructing) member auteur from it, which is using the copy constructor -- which you deleted!

There are two ways of working around this:

1 - Don't delete Auteur's copy constructor. Since this class doesn't appear to manage any resource, that's fine.

2 - Give Oeuvre's constructor the parameters it needs to properly initialize an Auteur. I wouldn't go with this one, because it certainly doesn't concern this class to do such thing.

Upvotes: 1

Related Questions