1

I'm having trouble distinguishing the differences when initializing objects using constructors.

I've also read that Bjarne recommends the {} syntax but that it's mostly equivalent to the () syntax so I think that I understand that part.

The problem occurs on line 40 with Car b();.

#include <iostream>
#include <conio.h>

class Car
{
public:
    Car() // initialize car
    {
        std::cout << "Default constructor called" << std::endl;
        ++carNumber;
    }
    ~Car() // destroy car
    {
        --carNumber;
    }

    static int getCarNumber() { return carNumber; };

private:
    static int carNumber;
};
int Car::carNumber = 0;

int main() {

    // Equivalent
    std::cout << "Car a{};" << std::endl;
    Car a{};
    std::cout << "Car d = Car{};" << std::endl;
    Car d = Car{};

    // Equivalent
    std::cout << "Car e;" << std::endl;
    Car e;
    std::cout << "Car c = Car();" << std::endl;
    Car c = Car();


    std::cout << "Car b(); " << std::endl;
    Car b(); // this line

    std::cout << "CarNumber: " << Car::getCarNumber() << std::endl;
    _getch();
    return 0;
}

This is the output of the program:

Car a{};
Default constructor called
Car d = Car{};
Default constructor called
Car e;
Default constructor called
Car c = Car();
Default constructor called
Car b();
CarNumber: 4

I'm confused with "Car b()". I think the compiler is interpreting it as a funcition that returns a Car, but if that's the case I don't see where the function may be implemented (it should cause an error?").

I expected "Car b()" to call the default constructor I made but it doesn't.

Clifford
  • 88,407
  • 13
  • 85
  • 165
Juan
  • 31
  • 6
  • Hint -- How would you declare a function called `b` that takes no parameters and returns a `Car` object? See the ambiguity? Also, you should be aware that you can declare functions all over the place and not implement them. The C++ compiler doesn't care -- it simply is trusting you that the function is implemented somewhere. The **linker** (not compiler) will care if you attempt to call the function and the function cannot be found. – PaulMcKenzie Jun 16 '19 at 18:30
  • I see what you mean. What is Car b(); doing then? Is it ignored by the compiler? My program doesn't crash. – Juan Jun 16 '19 at 18:33
  • It is a function declaration. No different if you had intended to actually declare a function. – PaulMcKenzie Jun 16 '19 at 18:35
  • Thank you very much. I guess I got lost in the syntax! – Juan Jun 16 '19 at 18:36
  • Just in passing, the sample code here could have been much smaller -- almost all of `main` and most of the definition of `Car` have nothing to do with the question. – Pete Becker Jun 16 '19 at 20:00

1 Answers1

0

This is one of the apparently nonsenses of C++. The grammar is so complex that took years for compilers to agree on what is C++ and what is not, and it's even officially ambiguous. The ambiguity is solved by a rule that more or less says

if something is ambiguous and could be both a function declaration or an object definition then it's a function declaration

The declaration of a function returning a Car, taking no parameters and named b would be

Car b();

so that's what the compiler gets.

This absurd rule is at the core of the "most vexing parse" trap of C++.

Why should one declare a function inside a code block? No one knows... but you can.

6502
  • 112,025
  • 15
  • 165
  • 265
  • 1
    "*Why should one declare a function inside a code block?*" Because you could do it in C, and to keep that declaration from leaking out to other blocks of code. – Nicol Bolas Jun 16 '19 at 18:43
  • @NicolBolas: this was a nonsense in "C" too, but anyway "C++" had no reason to copy that design error (I'm sure you know that not all "C" code also qualifies as valid "C++"). – 6502 Jun 16 '19 at 18:49
  • 2
    OK, so in this alternate C++ of yours... how do you allow `Car b();` to work to create a *global variable* (or namespace-scoped one) instead of a global/namespace declaration of a function `b` that returns a `Car`? At the end of the day, even if you make it so that `Car b()` work in a function, you still have the problem. – Nicol Bolas Jun 16 '19 at 19:28
  • @NicolBolas: Function declaration at a block scope is not useful, forbidding it would help a bit with the error messages you get when you stumble in variations of the most vexing parse rule. C++ syntax is a real mess and some parts are difficult to fix, but block-local function declarations is not one of them (remove the possibility and the C++ world becomes a sightly better place). The problem remains at top level, but in my experience this is not what bites most often (also I really hate block-level function declarations because I've to work with code that uses them, go figure). – 6502 Jun 16 '19 at 21:29