Является ли это функцией типа typeofType () или объектом? - PullRequest
4 голосов
/ 07 января 2009
#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 *'
}

Ответы [ 4 ]

22 голосов
/ 07 января 2009

Ошибка в первой строке основной функции:

name varName();

Вы не создаете экземпляр класса name с конструктором по умолчанию, вы фактически объявляете новую функцию с именем varName без параметров, которые возвращает имя экземпляр.

Вместо этого вы должны написать:

name varName;
8 голосов
/ 07 января 2009

Я думаю, что стоит рассказать вам о подобной проблеме, которая также вызывает проблемы:

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());
}

Что на самом деле представляет собой функция b, которая возвращает bar и принимает в качестве первого аргумента указатель на функцию, которая возвращает foo без аргументов. Это так же, как:

bar b(foo(*)());

Если вы хотите создать объект bar, инициализированный с помощью созданного по умолчанию foo, поставьте вокруг аргумента скобки. Это делает его больше не похожим на объявление функции, и компилятор интерпретирует его так, как вы хотите:

bar b((foo()));

Есть также неочевидные случаи, когда ошибка компилятора должна возникать. GCC понимает это неправильно, но Comeau понимает это снова. Рассмотрим следующий фрагмент

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

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

Вы, вероятно, ожидаете, что это принимает статическую константу и приводит ее к int, инициализируя переменную v равной 0? Нет, в соответствии со Стандартом это не будет, потому что инициализатор может быть интерпретирован как объявление, в соответствии с чистым синтаксическим анализом, как показано ниже

struct foo {
  static int value;
};

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

Всякий раз, когда инициализатор можно интерпретировать как объявление, в такой ситуации вся декларация будет объявлять функцию. Итак, строка в main объявляет функцию, подобную следующей, опуская лишние и бессмысленные скобки

int v(int foo::value);

И это приведет к ошибке компилятора при разборе объявления функции, поскольку имя параметра функции может быть не квалифицированным.

1 голос
/ 07 января 2009

Стоит также отметить, что ваша функция add () не имеет длительных эффектов - все, что она делает, это присваивает значение pname, которое является копией указателя, который вы передаете в него. Если вы действительно хотите иметь эту ручку назначения, вам нужно будет передать указатель по ссылке как «name * & pname».

0 голосов
/ 07 января 2009
name varName();

интерпретируется как объявление локальной функции. Чтобы вызвать конструктор по умолчанию, используйте

name varName;

вместо этого. Да, очень обидно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...