-1

SOLVED:

My mistake was using the dot instead of a = so changing:

myRect.Rect(pt1,pt2,pt3,pt4); <-- didn't work
myRect = Rect(pt1,pt2,pt3,pt4); <-- worked

(thanks for the quick help! Even for getting a -1 for this question)

Initial QUESTION:

I tried to make my problem as simple as possible. I don't know why this doesn't work. How do I change the points of a created rect? My guess is that I am not working correctly with the 'this -> operator'.

I don't even know how to correctly title my question, any hints for better labeling?

point.h

class Point
{
private:
public:
    int X;
    int Y;
};

point.cpp

Point::Point() {
    X = 0;
    Y = 0;
}

rect.h

class Rect
{
private:
    Point P1, P2, P3, P4;
public:
    Rect();
    Rect(Point p1, Point p2, Point p3, Point p4);
};

rect.cpp

Rect::Rect(Point p1, Point p2, Point p3, Point p4) {
    this -> P1 = p1;
    this -> P2 = p2;
    this -> P3 = p3;
    this -> P4 = p4;
}

main.cpp

int main(){

    Rect myRect;

    Point pt1;
    Point pt2;
    Point pt3;
    Point pt4;

    myRect.Rect(pt1,pt2,pt3,pt4);
}

ErrorMessage:

Invalid use of 'Rect::Rect'

Cache Staheli
  • 3,510
  • 7
  • 32
  • 51
obrob
  • 843
  • 1
  • 8
  • 20
  • 3
    Just a side note: 2 `Points` are enough to define a `Rect`. – πάντα ῥεῖ Jun 24 '16 at 18:07
  • 2
    Where is the `#include rect.h` in your `main.cpp`? – PaulMcKenzie Jun 24 '16 at 18:08
  • 1
    You don't call a constructor *later*, It is called on object creation(usually immediately following the `Point-of-Declaration`). The case of *later* is when you use `placement-new`. Please look for a [good C++ book](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) and read – WhiZTiM Jun 24 '16 at 18:09
  • 2
    You probably want to remove the 1st declaration and write `Rect myRect(pt1,pt2,pt3,pt4);` instead. – πάντα ῥεῖ Jun 24 '16 at 18:09
  • Please refrain from using the `this->` syntax. It is not needed and extra typing. – Thomas Matthews Jun 24 '16 at 18:30
  • Please note that if you use assignment you will first construct a Rect object using the default constructor, then construct another Rect object and assign that to myRect. It's more efficient to do the initialization you want at the declaration. – drRobertz Jun 24 '16 at 19:46

3 Answers3

2

You are mistaking a constructor for a method. Take a look at the answer to this question (it's about Java, but similar ideas apply): https://stackoverflow.com/a/25803084/4816518.

To summarize, Constructors (including the default constructor) are used to initialize the object, don't return anything (if you don't include the object being created), are named the same as the class (e.g. Rect::Rect is the constructor for the Rect class.
On the other hand, methods are used to invoke some behavior on an already-created object. Also, unlike constructors, they can have a return type.

So, instead of this

Rect myRect;

Point pt1;
Point pt2;
Point pt3;
Point pt4;

myRect.Rect(pt1,pt2,pt3,pt4);

You probably want something more along the lines of this:

Point pt1 = Point(0,0); //Didn't see this constructor, but you probably need it.
Point pt2 = Point(1,1); //I'm choosing random values.
Point pt3 = Point(0,1);
Point pt4 = Point(1,0);

myRect = Rect(pt1,pt2,pt3,pt4); //this creates the Rect with the given points.

Or this:

Point pt1(0,0);
Point pt2(1,1);
Point pt3(0,1);
Point pt4(1,0);

Rect myRect(pt1,pt2,pt3,pt4);

Or even this more simplified version (However, you would need to have a Point::Point(int x, iny y) constructor declared, and Rect's constructor would need to take const Point& parameters).

Rect myRect(Point(0,0),Point(1,1),Point(0,1),Point(1,0));

A constructor (Point::Point() and Rect::Rect(Point p1, Point p2, Point p3, Point p4) in your case), creates the object, and then you can execute methods on it.

Rect myRect declares a variable and instantiates it with the default constructor. If you want to pass in arguments to the object, you need to call a constructor with parameters like Rect(Point p1, Point p2, Point p3, Point p4).

Community
  • 1
  • 1
Cache Staheli
  • 3,510
  • 7
  • 32
  • 51
  • 3
    *`Rect myRect` only declares a variable. It doesn't instantiate it.* Not true. It creates an instance using the default constructor. If there is no default constructor, the compiler will produce an error on that line. – R Sahu Jun 24 '16 at 18:18
  • @RSahu Oops. Was thinking java. Fixed. – Cache Staheli Jun 24 '16 at 18:19
  • 1
    And if you change the `Rect` constructor to take `const Point&` parameters, and give `Point` a constructor that takes input values, you won't need the local `Point` variables at all: `Rect myRect(Point(0,0), Point(1,1), Point(0,1), Point(1,0));` – Remy Lebeau Jun 24 '16 at 18:34
1

There are two errors.

1. you need to declare a default constructor for Point in order to create the constructor that you defined outside of the class.

class Point
{
private:
public:
    Point(); // <-- add this
    int X;
    int Y;
};

2. You don't need to use the class access dot operator to use Rect(). This is because Rect() is a constructor, and calls to a constructor do not need to be called on an object, as is done for functions.

Rect myRect;
myRect = Rect(pt1,pt2,pt3,pt4);

Or

Rect myRect = Rect(pt1,pt2,pt3,pt4);

Or

Rect myRect(pt1,pt2,pt3,pt4);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
HumanTorch
  • 349
  • 2
  • 5
  • 16
1

You are first constructing myRect with the default constructor (Rect::Rect()) and then you try to call the other constructor as a member function. (That is the invalid use)

Instead, use the other constructor directly: Rect myRect(p1, p2, p3, p4)

Regarding this->P1 you don't need to use this to access member variables. And for constructors, using initializer lists as Rect(Point p1, Point p2, Point p3, Point p4) :P1{p1},P2{p2},P3{p3},P4{p4} {} is preferred to doing assignment in the constructor body, for the same reason: if you don't initialize members they will be default constructed before entering the constructor body.

drRobertz
  • 3,490
  • 1
  • 12
  • 23