Hello everybody,

I wrote a test source code about 2 classes point and circle. These classes illustrate the center of a circle (point class) and its radius (circle class). Circle class inherits point class. Here's the code:

#include <iostream>
using namespace std;

class point {
   private:
    int x, y;

  public:
  point() {}
   point(int x, int y);
   point(const point& d);
   int getX() { return x; }
   int getY() { return y; }

};

class circle : public point {
     private:
      int radius;

    public:
      circle(point p, int r);
      int getRadius() { return radius; }
      bool operator>(circle c);
};


int main() {
   circle c1(point(0, 1), 2), c2(point(2, 2), 1);
   if (c1 > c2)
    cout << "center: " << c1.getX() << ", " << c1.getY() << " radius: " << c1.getRadius() << endl;
    else
     cout << "center: " << c2.getX() << ", " << c2.getY() << " radius: " << c2.getRadius() << endl;
    return 0;
}

point::point(int x, int y) {
   this -> x = x;
   this -> y = y;
}

point::point(const point& d) {
   x = d.x;
   y = d.y;
}

circle::circle(point p, int r)  {
    point(p);
      radius = r;
}

bool circle::operator>(circle c) {
  return (radius > c.radius);
}

My question refers to that specific piece of code:

circle::circle(point p, int r)  {
    point(p);
     radius = r;
}

When i call copy constructor point() inside the body of circle constructor (as above) then compiler complains showing the message: "declaration of 'point p' shadows a parameter"
When i change that code into the following then everything is ok:

circle::circle(point p, int r) : point(p) {
      radius = r;
}

Why is that happening? I thought that i could call a constructor inside other's body..Thank you for your time!

I guess a parameterized constructor of a base class cannot be called inside a derived class constructor. It has to be through initialization lists. I'm not fully sure though. It is only in Java that a keyword super is provided and it is called through super keyword in the very first line of the derived class constructor. Because point(p) is not inherited .

I'm not sure if this configuration is dictated by your assignment, but, in my opinion, I think your circle class should have a point member ("composition") instead of deriving from the point class. What you are seeking is more of "has-a" relationship ("a circle has a point(center)") instead of an "is-a" relationship ("a circle is a point"-doesn't really fit). I realize the is-a/has-a suffers from some limitations, so that's why I'm presenting it as an opinion.

Edited 5 Years Ago by jonsca: n/a

Thank you guys for your instant replies...I'll check it out more thoroughly... But i'd like to hear more opinions about this subject, if someone is pretty sure about that..Thanks again

Edited 5 Years Ago by vanalex: n/a

With the inheritance you have, the base class has to be constructed before the derived class. Hence your second option is the right one.

Now I totally support Jonsca comment. A circle is not a point. So Circle shouldn't derive from Point. I would write

class circle
{
private:
    int radius;
    point p;
public:
    circle(const point & p_, int r_);
    int getRadius() const { return radius; } // Added const as this member funct doesn't change the Circle class.
    const point & getCenter() const {return p;} // Added this other funct to get the center.
    bool operator>(const circle & c); // Less time consuming to pass it by reference
};

circle::circle(point p_, int r_) : radius(r_), p(p_)
{
}

// The rest remains unchanged.

For your point class, I would also make these small changes

class point
{
private:
    int x, y;
public:
    point() {} // Do you need this one ? I would make default parameters for the next constructor.
    point(int x_=0, int y_=0);
    point(const point& d); // Do you need this ? The default copy constructor will just do the same.
    int getX() const { return x; } // Again some constness...
    int getY() const { return y; } 
};

point::point(int x_=0, int y_=0) : x(x_), y(y_)
{}

When you write

point::point(int x, int y) {   this -> x = x;   this -> y = y;}

This is wrong. All data members are initialized before entering the constructor. For built-in types there's no guarantee it's initialized at all before entering the constructor. So what you wrote yield to undefined behaviour.
You must initialize all your datamember before entering the constructor. When I write

circle::circle(point p_, int r_) : radius(r_), p(p_)
{
}

I call the copy-constructor of point passing p_ as its parameter. Same for radius, but it's an int (and so a built-in type). It much more efficient than calling the default constructor, and then calling the assignement operator in the body of the constructor.

Edited 5 Years Ago by akhena: n/a

point::point(int x, int y) {   this -> x = x;   this -> y = y;}

This is wrong. All data members are initialized before entering the constructor. For built-in types there's no guarantee it's initialized at all before entering the constructor. So what you wrote yield to undefined behaviour.

Other than the fact that the member variables are being masked by the local variables (which is a big no-no, but has been correctly compensated for by using the this pointer), there's nothing wrong with that. They're simply performing the initializations in the body of the constructor instead of the initialization list. There is no undefined behavior.

That being said, you are correct that it's more efficient to use an initialization list for user-defined classes. In fact, under certain circumstances, it's required syntax. But for built-in types, such as int, it's really a non-issue.

Edited 5 Years Ago by Fbody: n/a

This question has already been answered. Start a new discussion instead.