0

I need help with an issue. I have been reminding myself how to use C++ and got back to inheritance. I have been using the tutorials on cplusplus.com for the code below

class Shape
{
    protected:
        int width, height;
    public:
        Shape(int w, int h) : width(w), height(h) { }
        Shape()
        {
            width = 1;
            height = 1;
        }
        void set_values (int w, int h)
        {
            width = w;
            height = h;
        }
};

class Rectangle : public Shape
{
    public:
        Rectangle()
        {
            width = 1;
            height = 1;
        }
        Rectangle(int w, int h) : width(w), height(h) { }
        ~Rectangle() { }

        int area ()
        {
            return (width * height);
        }
};

However whenever I run a test, it always fails on the Rectangle's constructor. That seems to be where it always fails. Can anyone see where I have gone wrong?

Jeremy Beare
  • 489
  • 3
  • 8
  • 22

3 Answers3

3

You can't directly initialize base class data members in a derived class constructor, because these data members are already initialized by the base class. You need to explicitly call the base class constructor:

Rectangle(int w, int h) : Shape(w, h) { }

You can also simplify Rectangle(). There is no need to assign values of 1 to data members that have already been initialized to that value:

Rectangle() : Shape() {}

or

Rectangle() {} // Shape() implicitly called

or, in C++11,

Rectangle() = default;

Alternatively, in C++11, you can say

class Rectangle : public Shape
{
 public:
  using Shape::Shape; // "inherit" shape's constructors
};
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • well...are you sure the ctor could be `using`? It cannot compile with Vs2013. – Cigany Mar 11 '14 at 08:39
  • 1
    @Cigany Then VS2013 is not C++11 compliant WRT this feature. I don't use VS so I don't run into this problem. You can try with the latest clang++ or g++. – juanchopanza Mar 11 '14 at 08:41
  • my fault, it compile with g++4.8 – Cigany Mar 11 '14 at 08:48
  • [On msdn](http://blogs.msdn.com/b/vcblog/archive/2013/12/02/c-11-14-core-language-features-in-vs-2013-and-the-nov-2013-ctp.aspx) Inheriting constructors – Cigany Mar 11 '14 at 09:01
1
Rectangle(int w, int h) : width(w), height(h) { }

width and shape are members of the base class, Shape. You can't initialize them in a derived class' constructor because the base class' constructor takes care of that.

The reason this constructor works

Rectangle()
{
    width = 1;
    height = 1;
}

is because that's assignment, not initialization.

Remember, before the constructor of the most derived class runs, the constructors of all base classes will be run.

You can do explicitly say which constructor of a base class you want to call by saying:

Rectangle(int w, int h) : Shape(w, h) { }

or, if the default constructor would be sufficient, just don't do anything (the compiler will call it automaticaly, then).

jrok
  • 54,456
  • 9
  • 109
  • 141
  • 1
    N.B. I recommend that you find a better source than the tutorial from cplusplus.com (like some [good book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list)). It's just not very good. I should know, because I started learning C++ from it :) – jrok Mar 11 '14 at 08:14
0

You cannot use the super class members in sub-class constructor initialization list.

Following code will work:

class Rectangle : public Shape
{
    public:
        Rectangle()
        {
            width = 1;
            height = 1;
        }
        Rectangle(int w, int h)
         : Shape(w,h) { }
...
};
vmax33
  • 643
  • 5
  • 13