4
#include<iostream>
class name
{
public:
    int a;
    name():a(0){};
};
void add(name * pname)
{
    pname = NULL;
}
int main()
{
    name varName();
    name * pName = new name();
    add(pName);
    add(&varName);//error C2664: 'add' : cannot convert parameter 1 from 'name __cdecl *)(void)' to 'name *'
}
yesraaj
  • 46,370
  • 69
  • 194
  • 251

4 Answers4

22

The error is on the first line of the main function:

name varName();

You are not creating an instance of class name with the default constructor, you are actually declaring a new function called varName, with no parameters, which returns a name instance.

You should instead write:

name varName;
MiniQuark
  • 46,633
  • 36
  • 147
  • 183
  • 1
    I ran into this one a thousand times! ;-) I think that the C++ language is a successful "meme" (check the Wikipedia): it is successful because it allows developers to feel intelligent when they finally grasp yet another gotcha. It flatters them, that's why they like it. ;-) – MiniQuark Jan 07 '09 at 12:41
  • i so much like this sort of question :) it causes a "aha!" effect on the readers, and it gives much points to a right answer :) +1 indeed – Johannes Schaub - litb Jan 07 '09 at 12:54
  • is there any thing similar to this kind of syntax in c++...that one should know abt – yesraaj Jan 07 '09 at 12:59
  • rajKumar, see below for another example – Johannes Schaub - litb Jan 07 '09 at 13:00
  • My mind has been boggled. I've never run into it in years of C++, but it's a definite +1. – Jeff M Jan 07 '09 at 13:31
8

I think it's worth telling you about a similar problem, that also causes trouble:

struct foo { };
struct bar { bar(foo f); };

int main() {
  // does *not* create a bar object initialized by a default constructed 
  // foo object.
  bar b(foo());
}

What b really is is a function that returns a bar and takes as first argument a pointer to a function that returns a foo taking no arguments. It's the same as:

bar b(foo(*)());

If you want to create a bar object initialized by a default constructed foo, put parentheses around the argument. That makes it doesn't look like a function declaration anymore, and the compiler will interpret it like you want:

bar b((foo()));

There are also non-obvious cases where a compiler error should be risen. GCC gets this wrong, but Comeau gets it right again. Consider the following snippet

struct foo {
  static bool const value = false;
};

int main() {
  int v(int(foo::value));
}

You will probably expect that this takes the static constant, and casts it to int, initializing the v variable to 0? No, it won't according to the Standard, because the initializer can be interpreted as a declaration, according to pure syntax analysis, as the following shows

struct foo {
  static int value;
};

// valid, parentheses are redundant! Defines `foo::value`.
int (foo::value); 

Whenever the initializer can be interpreted as a declaration, in such a situation whole the declaration will declare a function. So, the line in main declares a function like the following, omitting the redundant and meaningless parentheses

int v(int foo::value);

And this will cause a compiler error when parsing the function declaration, because a function parameter name may not be qualified.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • great answering my next question ...even before asking it – yesraaj Jan 07 '09 at 13:01
  • @litb what determines a function parameter as pass by value or pass by reference is it just function signature or how does the function is called – yesraaj Jan 07 '09 at 13:11
  • rajKumar, i answered the question in the past, trying to set up a definition for it: http://stackoverflow.com/questions/410593/pass-by-reference-value-in-c#410857 . or do you mean something else? – Johannes Schaub - litb Jan 07 '09 at 13:27
  • _that_ is _wicked_! I didn't know that foo() would be an alias for foo(*)() ... thanks! – xtofl Jan 19 '09 at 14:51
  • yeah. it's the same in parameter lists only though. otherwise foo() is indeed the type of a function rather than the type of a function pointer (much like char[3] is the type of an array, while char(*)[4] is an array pointer) – Johannes Schaub - litb Jan 19 '09 at 19:35
1

It's also worth noting that your add() function doesn't have any lasting effects -- all it's doing is assigning a value to pname, which is a copy of the pointer you pass into it. If you want to actually have that assignment stick, you would need to pass the pointer by reference as "name*& pname".

JohnMcG
  • 8,709
  • 6
  • 42
  • 49
0
name varName();

is interpreted as a local function declaration. To invoke the default constructor, use

name varName;

instead. Most vexing, yes.

Daniel Paull
  • 6,797
  • 3
  • 32
  • 41