0

I'm trying to create a class in C++ which forbids the use of the default constructor.
Nevertheless, I think I'm failing, or I'm not understanding what is happening behind the scenes. Here is what I have so far:

class Point {
public:
        float x;
        float y;
        Point(float newX, float newY); //Definition is irrelevant
        Point() = delete; //Default or "empty" constructor is forbidden, so deleted
}
/* ... */
int main(void)
{
        Point a(1, 2); //Ok, should be available
        Point b; //Ok, does not compile
        Point c(); //Not ok, it does compile :(
}

My intended behavior is for point c not to compile. I'd appreciate help in generating such a behavior, or if not possible, an explanation of why this works like that.

Thank you in advance

Manuel W.
  • 65
  • 1
  • 6
  • I got an answer in this prior thread: https://stackoverflow.com/questions/40683637/how-to-create-a-c-11-non-default-constructible-allocator. Note that the posted code in the question was updated to show how to do this. – rcgldr Dec 01 '17 at 20:14
  • 1
    `c` is not an object. So the default c'tor isn't invoked, don't worry. – StoryTeller - Unslander Monica Dec 01 '17 at 20:14

3 Answers3

8

What is happening is a vexing parse. You're not declaring an object, but a function with name c and return type of class Point.


Declaring any constructor will prevent compiler from generating default constructor, so declaration with =delete is superflows.


Aggregate initialization

If you know the order, you don't even need constructor:

Point p{newX, newY};

Will work just fine.


Uniform initialization syntax

In the future, to avoid such cases, use {}:

Point p{}; //default constructs
Incomputable
  • 2,188
  • 1
  • 20
  • 40
  • While you may argue that the `=delete` is superfluous, it can also be said that it serves as a comment that explicitly shows that the programmer intended for that constructor not to be created. – TCD Jan 29 '22 at 23:10
  • @TCD, I would also expect s comment why. In this case, it is pretty clear that default init will cause problems with uninitialized values. – Incomputable Jan 30 '22 at 05:38
  • A default constructor does not **have** to cause problems. In this case, the implicitly generated one could. You could write an explicit `Point() : x{0}, y{0}{}` as a default constructor. If you see just the overloaded constructor, then you can assume that the programmer probably didn't just forget to write a default constructor. But there is a chance that they didn't think about it and just forgot to add it. However, if you see it explicitly deleted, then you know that that was his intention. – TCD Jan 30 '22 at 20:14
2

The line

    Point c(); //Not ok, it does compile :(

Is not interpreted as creating an object c of type Point, it is interpreted as declaring a new function c which return a Point and takes no arguments. Look here: https://en.wikipedia.org/wiki/Most_vexing_parse

There also no need for this line:

    Point() = delete; //Default or "empty" constructor is forbidden, so deleted

If you declare any constructor, then the default constructor is overwritten.

1

It does compile, but only because it is not what you think it is. You correctly deleted the default constructor. Actually already declaring a non default constructor prevents the class from being default constructible:

struct Foo {
    Foo(int);
}

Foo x; // wont compile

Declaring the default constructor as deleted is good practice as it explicitly states that the default constructor is left out on purpose.

Why did it compile?

Foo x();

declares a function that returns a Foo. This is knows as the most vexing parse.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185