Reputation: 2121
I just finished creating a "Point" class and was working on a "Line" class that has two Point objects (Point startpoint and Point endpoint) as data members. I created a constructor in my Line class that accepts two Point objects as arguments and had originally created it as follows:
Line(const Point& p1, const Point& p2)
{
startpoint = p1;
endpoint = p2;
}
Everything was fine, but then I decided I would use a member initialization list instead of assigning the members to p1 and p2 in the body, just because... But when I changed it to:
Line(const Point& p1, const Point& p2): startpoint(p1), endpoint(p2)
{
}
I get an error saying "no instance of constructor "Point::Point" matches the argument list" and didn't understand what this meant exactly.
Why doesn't the member initialization list work here?
Thanks.
edit: Sorry, I didn't know if the details of my point class was relevant or not:
// Point.h
class Point
{
private:
double x;
double y;
public:
Point();
Point(Point& p);
Point(double x1, double y1);
~Point();
double X() const;
double Y() const;
void X(double newx);
void Y(double newy);
};
// Point.cpp
#include "Point.h"
Point::Point(): x(0), y(0)
{
}
Point::Point(Point& p)
{
x = p.x;
y = p.y;
}
Point::Point(double x1, double y1): x(x1), y(y1)
{
}
Point::~Point()
{
}
double Point::X() const
{
return x;
}
double Point::Y() const
{
return y;
}
void Point::X(double newx)
{
x = newx;
}
void Point::Y(double newy)
{
y = newy;
}
Upvotes: 0
Views: 371
Reputation: 67822
The member initialization depends on Point
having a public copy constructor, since you explicitly calling Point::Point(const Point&)
.
If that doesn't exist or is not accessible, you can't call it. If you can't call it, it isn't because the initialization list doesn't work, though.
Presumably Point
has an accessible assignment operator, if the first version works.
Just to confirm, now you've pasted the source for Point
, the copy constructor should look like:
Point::Point(const Point &other) : x(other.x), y(other.y) {}
(you might as well get comfortable using the initializer list).
The key change is the argument must be a const
reference: this prohibits accidentally damaging the source object when copying.
Upvotes: 10
Reputation: 254741
Point(Point& p);
Your copy constructor requires a non-const
reference to a Point
. This means your can't initialise a point from a const
reference, which the initialiser list requires. Assignment works because you haven't implemented your own copy-assignment operator, so the implicit one is used.
You should either change the copy constructor to Point(Point const &);
or, better still, remove it entirely since it does exactly the same as the implicitly-defined one would. Likewise, there's no point in defining your own destructor unless it either needs to do something, or needs to be virtual or non-public.
Upvotes: 0
Reputation: 34664
In
Line(const Point& p1, const Point& p2): startpoint(p1), endpoint(p2)
You are invoking Point::Point
with p1
(p2
respectively) which has type const Point&
, i.e. you promised never to change the parameters given to Line::Line
. Now, let's look at your Point
class. The only method with a matching number of arguments is
Point(Point& p);
Which takes a Point&
, something which is okay to modify inside Point::Point(Point&)
. Thus, you cannot pass p1
(or p2
) there because you already promised it would never be changed.
Make your constructor
Point(const Point& p);
and you can use the initialiser list like you do.
Upvotes: 3