bqui56
bqui56

Reputation: 2121

Why can't I use a member initialization list here?

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

Answers (3)

Useless
Useless

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

Mike Seymour
Mike Seymour

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

bitmask
bitmask

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

Related Questions