Meditation, The Art of Exploitation

Thinking? At last I have discovered it--thought; this alone is inseparable from me. I am, I exist--that is certain. But for how long? For as long as I am thinking. For it could be, that were I totally to cease from thinking, I should totally cease to exist....I am, then, in the strict sense only a thing that thinks.

Wednesday, April 26, 2006

Declaration or Definition?

Originally by Jerry Coffin from clcm (editted formatting)

> Given a class Foo:
> class Foo
> {
> Foo() { ... }
> ~Foo() { ... }
> };

As it stands at the moment, you've made Foo::Foo (and ~Foo) private, so you can't create any objects of type Foo. Presumably that was just a slip that entered during posting though. Something like this might be more informative:

struct Foo {
Foo() { std::cout << " ctor"; } ~Foo() { std::cout << " dtor"; }

};

This allows the rest of the code to compile and gives a bit of information about when the ctor and dtor are invoked.

> What's the difference between the following four functions?

> void bar() { Foo; }

This is ill-formed. "Each declarator contains exactly one declrator-id; it names the identifier that is declared." I believe a conforming compiler is required to issue a "diagnostic" for this code (though it can choose to compile it anyway, and if so treat it more or less as it chooses). It looks like MS fails to issue a diagnostic, but interprets this in an obvious way -- as not really declaring anything, so it's basically a nop.

> void bar() { Foo(); }

I'm not _entirely_ certain but I think this is allowed, and should create a temporary object of type Foo() with default initialization.

> void bar() { Foo myFoo; }

This is definitely allowed. It defines an object named myFoo of type Foo that's default initialized.

> void bar() { Foo myFoo(); }

This is definitely allowed as well. Unfortunately, this is one that has probably thrown every C++ programmer on earth at least once (it certainly has me anyway). As the warning message you got implied, this is a function declaration. It declares a function named myFoo that takes no parameters and returns an object of type Foo.

Sections 6.8 and 8.2 of the standard give a number of similar examples -- some of which require careful reading to figure out why they're interpreted the way they are. For a couple of examples from section 8.2:

void foo(double a)
{
S x(int()); // function declaration
S y((int)a); // object declaration

}

Simplifying (quite) a bit, a pattern like this gives a function declaration:

type name(type);

where a pattern like this gives an object declaration:

type name(value);

If the parentheses are empty, the compiler treats it as an empty type specification instead of an empty value, so you end up declaring a function instead of an object.