-2

I am very new to c++ and would like to know if it is possible to do something like this:

Rectangle rect(Point(0, 0), 10, 10); // doesn't work

The idea is that Rectangle takes a Point object as well as width and height parameters. The constructors look like this:

Rectangle::Rectangle(Point & point, double width, double height) {
  this->point = point;
  this->width = width;
  this->height = height;
};

Point::Point(double x, double y) {
  this->x = x;
  this->y = y;
};

I can get the desired effect by doing this:

Point point(0, 0);
Rectangle rect(point, 10, 10); // this works

but I think it would be nice if I could instantiate my point directly in the arguments for a new rectangle. If this is possible, please let me know! Thanks!

Frank
  • 2,050
  • 6
  • 22
  • 40
  • 2
    make it a `const Point & point` – george_ptr Nov 16 '16 at 17:17
  • Take by value and the first one should work. – tkausl Nov 16 '16 at 17:17
  • For some reason I thought `point` goes out of scope. I was wrong. – tkausl Nov 16 '16 at 17:19
  • both should work fine :-) – Mohamed Moanis Nov 16 '16 at 17:20
  • 1
    It is 100% possible. You just need to remember that a temporary(what `Point(0, 0)` is) cannot bind to an lvalue reference. – NathanOliver Nov 16 '16 at 17:21
  • @Frank, What exactly doesn't work ? Is it compilation error or something else ? – ks1322 Nov 16 '16 at 17:23
  • @MohamedMoanis: No, only the `const&`. – Christian Hackl Nov 16 '16 at 17:24
  • @GeorgeAI if you post that in an answer I will accept it. Sorry for posting such a common sense question, but I was looking for quite some time at how to do this. I am coming from Javascript and c++ is a beast. – Frank Nov 16 '16 at 17:24
  • By the way: Use initialisation lists, not assignments. – Christian Hackl Nov 16 '16 at 17:24
  • Your first example compiles fine on VS 2013, so I'm guessing your compiler is stricter than mine! You should prefer member initialisation to assignment however. – djgandy Nov 16 '16 at 17:25
  • @djgandy: It's not "fine" if it produces a warning. – Christian Hackl Nov 16 '16 at 17:26
  • @ChristianHackl It doesn't produce a warning. Don't know what the OP is using however, or what the warning was. – djgandy Nov 16 '16 at 17:28
  • @djgandy: It does, if you use `/W4` or if you activate warning C4239 manually. It says: `warning C4239: nonstandard extension used : 'argument' : conversion from 'Point' to 'Point &' A non-const reference may only be bound to an lvalue`. With `/Za`, it's even an error. – Christian Hackl Nov 16 '16 at 17:36
  • @ChristianHackl oh you are absolutely right (y) – Mohamed Moanis Nov 16 '16 at 17:37
  • @ChristianHackl I am running /W4. Only way I can get it to show up is /Za or force enabling! Seems this has been covered before - http://stackoverflow.com/questions/16380966/non-const-reference-bound-to-temporary-visual-studio-bug – djgandy Nov 16 '16 at 17:42
  • @djgandy: The answers there just repeat what I just said. The warning will appear with `/W4`. I just tested it with an old Visual C++ 2013 installation on my computer. Are you sure you are testing the correct code and that you don't use some other compiler flags? Try a simple `cl /nologo /EHsc /W4 stackoverflow.cpp`. – Christian Hackl Nov 16 '16 at 17:45

3 Answers3

2

a "regular" reference cannot bind to a temporary, only constant reference (const T&) and r-value-reference (T&&)

in your first snippet, Point(0, 0) is a temporary, so it can't be bound to Point&, but in your second snippet, Point point(0, 0); is not a temporary, so it works.

in this case, since you don't try to modify the temporary, make it bind to a constant reference :

Rectangle::Rectangle(const Point & point, double width, double height)
David Haim
  • 25,446
  • 3
  • 44
  • 78
  • But then if I pass in an object that I defined before like in my second example, will my object be stored twice? – Frank Nov 16 '16 at 17:36
  • you should read about scopes in C++.. – David Haim Nov 16 '16 at 17:37
  • I am in the process of learning as much as I can, but I occasionally get stumped. But interestingly (at least to me) If I use the method in your answer and my second example, I get two separate objects rather than one, which is pretty nice. – Frank Nov 16 '16 at 17:39
0

It depends on how Rectangle is defined.

I'm assuming it looks something like this:

class Rectangle {
    Point point;
    double width, height;
    /*...*/
};

In which case, defining the Constructor like this will work:

Rectangle::Rectangle(Point const& p, double w, double h) {
    point = p;
    width = w;
    height = h;
}

Which will allow it to take a temporary (like you want) or take an lvalue (which is what your second example does).

If Rectangle is meant to store a reference to a point, that's almost certainly a design error, and you should change that.

Xirema
  • 19,889
  • 4
  • 32
  • 68
0

You can possibly instantiate in your argument list but you would not have the Point available outside the constructor. The point would be local to the constructor.

You could access the point as rect.point after that.

Edit:

Since you are trying to use a reference to point, this will not work.

Samir Jha
  • 16
  • 2