0

I haven't done C++ coding in some time, and my friend is having trouble with his homework. I never really worked with const, and it's making this a nightmare as I can't figure out the correct syntax for the constructor. Imagine I have this in dvd.h:

class DVD {
    const string title;
    int minutes;
    double price;

  public:
    DVD(const string t, int m, double p);
}

3 private member variables, the string is const. The constructor also takes a const string.

So now, in dvd.cpp I can do the following:

#include "dvd.h"

DVD::DVD(const string t, int m, double p) {
    const string title = t;
    minutes = m;
    price = p;
}

And all is well in the world. However, when I modify minutes in dvd.h to be const (which is how his professor structured the file), we have this in dvd.h:

class DVD {
    const string title;
    const int minutes; // Here is the change
    double price;

  public:
    DVD(const string t, int m, double p);
}

So, now that minutes is const, I get the following compilation errors:

assignment of read-only member 'DVD::minutes'   dvd.cpp
uninitialized member 'DVD::minutes' with 'const' type 'const int' [-fpermissive]    dvd.cpp

Which I suppose makes sense, because I'm trying to set a value into a const variable. So then I tried doing the same thing as with the const string title in dvd.cpp in order to resolve the error:

DVD::DVD(const string t, int m, double p) {
    const string title = t;
    const int minutes = m; // Was 'minutes = m;'
    price = p;
}

and got the following (1) errors and (1) warnings:

uninitialized member 'DVD::minutes' with 'const' type 'const int' [-fpermissive]    dvd.cpp
unused variable 'minutes' [-Wunused-variable]   dvd.cpp

So I guess I'm struggling to figure out what the darn syntax is for this... title and minutes are supposed to be const, but the constructor's parameter list for DVD takes only a const string. I can't figure out what I'm missing - it's been a while since I last coded in C++.

Chris Cirefice
  • 5,475
  • 7
  • 45
  • 75
  • 1
    Get used to member initialization X : member(value) {] –  Feb 05 '14 at 17:12
  • The syntax is always the same: if you want to *initialize* data members in some particular way, you do it in the constructor initialization list (although you can also do it at the point of declaration in C++11). What happens is that you cannot *assign* or modify `const` data members. – juanchopanza Feb 05 '14 at 17:14
  • @Csq You're probably right - like I said, it's been a long time since I last did C++. I completely forgot about initializer lists. It's interesting, I looked at the question linked by WhozCraig (before I posted this question), and I didn't really understand it when I read it. In any case, I understand it now so thank you for the comments :) – Chris Cirefice Feb 05 '14 at 17:43

2 Answers2

8
const string title = t;

That declares a local variable. All is not well with the world: you haven't set the member variable to the value you want. To initialise members, use the constructor's initialiser list:

DVD::DVD(const string t, int m, double p) :
    title(t), minutes(m), price(p)
{}

Your version tries to default-initialise each member (since they aren't mentioned in the initialiser list), then assign each of them. This doesn't work for members which can't be default-initialised (such as references, or class types without a default constructor) or assigned to (such as const members).

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • Thanks for clearing that up - what I *tried* to do is the usual way constructors work in the languages the I usually use, and I couldn't remember exactly how it was done in C++. Thanks :) – Chris Cirefice Feb 05 '14 at 17:45
3

You can initialize your const and non-const members simply like this:

DVD::DVD(const string t, int m, double p)
    : title(t)
    , minutes(m)
    , price(p)
{}

Note that, if you are using C++98/03, you may want to pass the string parameter as const& (to avoid useless and inefficient calls to string copy constructor):

DVD(const string& t, ...other stuff...)
    ... same init as above

If you are using C++11 (which implements move semantics), you can pass the string parameter by value, and std::move() from the value:

DVD::DVD(string t, int m, double p)
    : title(std::move(t)),
    , minutes(m)
    , price(p)
{}
Mr.C64
  • 41,637
  • 14
  • 86
  • 162