8

I have Simpletron.cpp which is an empty file, a Simpletron.h which declares a Simpletron class:

class Simpletron 
{    
public:
    Simpletron();
};

I called Simpletron() in my main.cpp:

#include <iostream>
#include "Simpletron.h"

int main(int argc, char *argv[]) 
{

    Simpletron s();
    std::cin.get();
}

The main function just runs smoothly without any warning or error. Why is that? How does that even compile if there is no inplementation the header file could link to?

Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
octref
  • 6,521
  • 7
  • 28
  • 44
  • 4
    @Smac89: Not when you declare it. Maybe I'm going crazy, but at least 7 other people are wrong too. This program should cause a linker error, [example](http://ideone.com/5m0ygK). – GManNickG Sep 24 '13 at 00:37
  • @octef: Please provide your real code and command line. For example, your class definition is missing a semicolon after it so this can't be the code you're compiling. – GManNickG Sep 24 '13 at 00:37
  • 1
    @GManNickG: [VC++ compiles it](http://rise4fun.com/Vcpp/pqw). I think the issue is the most-vexing-parse, personally. – Mooing Duck Sep 24 '13 at 00:40
  • 2
    @MooingDuck: That would require a name: `Foo x();`. And technically that's just plain vexing. The "most" vexing parse refers to `Foo x(Foo());`. – GManNickG Sep 24 '13 at 00:41
  • @Smac89 That's not accurate at all, if he declared the default constructor but didn't implement he should get a linking error. The compiler will not generate a default constructor unless none is declared. – Dan O Sep 24 '13 at 00:44
  • Adding the semicolon at the end of `Foo.h` and compiling with `g++ Foo.cpp -o Foo`, I get a link-time error: `Foo.cpp:(.text+0x17): undefined reference to `Foo::Foo()'` – Keith Thompson Sep 24 '13 at 00:45
  • 1
    @MooingDuck my version of vc most certainly does not compile the provided code. A linking error is generated as one would expect. Maybe an old vc bug. – Dan O Sep 24 '13 at 00:45
  • 2
    @MooingDuck your link seems to only compile to object file, but not linking. – yngccc Sep 24 '13 at 00:46
  • @MooingDuck Exactly, I'm using VS 2012 – octref Sep 24 '13 at 00:47
  • 4
    Surprise surprise. Your original example is completely different than your actual code. – Benjamin Lindley Sep 24 '13 at 00:48
  • @BenjaminLindley uhh.. how is that the case? He just changed Foo to Simpletron and fixed the missing ';' – Dan O Sep 24 '13 at 00:49
  • @BenjaminLindley What's the difference? I was just trying to use the universal class Foo and while modifying missed a semicolon. – octref Sep 24 '13 at 00:49
  • 4
    @DanO: Look again. `Foo();` vs. `Simpleton s();` -- One is a constructor call, the other is a function declaration. – Benjamin Lindley Sep 24 '13 at 00:49
  • @BenjaminLindley I'm getting the same linking error regardless of the syntax I choose for the constructor call. This is not a vexing parse issue. – Dan O Sep 24 '13 at 00:50
  • @BenjaminLindley Oh, you are right. My bad sorry. – octref Sep 24 '13 at 00:50
  • 2
    Changing `Simpletron s();` to `Simpletron s;` triggers a linker error. – Keith Thompson Sep 24 '13 at 00:52
  • 4
    @DanO: Considering the fact that `Simpletron s();` isn't a constructor call, I don't really understand what you mean by "regardless of the syntax I choose for the constructor call". – Benjamin Lindley Sep 24 '13 at 00:53
  • @BenjaminLindley Aha, you are correct. – Dan O Sep 24 '13 at 00:55
  • Everyone else knew that. – Jim Balter Sep 24 '13 at 01:28
  • Possible duplicate of [Default constructor with empty brackets](https://stackoverflow.com/questions/180172/default-constructor-with-empty-brackets) – L. F. May 25 '19 at 05:02

3 Answers3

25

This line:

Simpletron s();

is a function prototype, declaring a function named s, returning a Simpletron and taking no arguments. It does not create a Simpletron instance named s.

Now you might ask, why doesn't the linker complain about the non-existent s() function instead? Well, since you're only declaring s() but never actually calling it, it's not actually referenced anywhere during linking, so you get no link error.

chappjc
  • 30,359
  • 6
  • 75
  • 132
Nikos C.
  • 50,738
  • 9
  • 71
  • 96
13
Simpletron s();

This is function declaration, not an object instantiation. The empty parenthesis tells the compiler this function takes no arguments and returns an object of type Simpletron by value, so no constructors are called. The correct syntax is without the parameters:

Simpletron s; // You will get an error on this line, as initially expected

C++11 adds a syntactical feature that avoids this ambiguity:

Simpletron s{}; // same as default-initialization
David G
  • 94,763
  • 41
  • 167
  • 253
5
    Simpletron s();

This is a classic case of "vexing parse"; for the compiler, you are not creating a variable s of type Simpletron, but you are declaring a function named s, taking no parameters and returning a Simpletron object.

This comes from the fact that this expression could be interpreted both as a function declaration and as a variable declaration; since to declare the variable there's an easy alternative (namely, just omit the parentheses) the standard mandates to interpret this as a function declaration.

This passes without problems the compiling phase (the compiler doesn't need to have the definitions of all the methods, just the declarations), and probably the linker doesn't give any error since no instance of Simpletron is actually created, so it never needs to actually look for the constructor definition (although I don't think that it's guaranteed not to give errors, a particularly thorough compiler/linker couple should be able to give you an error for the missing constructor anyway).

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299