Ошибка: запрос члена '..' в '..', который имеет не классный тип
У меня есть класс с двумя конструкторами: один без параметров и один с одним параметром.
Создание объектов с использованием конструктора, который принимает один параметр, работает как ожидалось. Однако, когда я пытаюсь создать объекты с использованием конструктора без параметров, возникает ошибка.
Например, если я компилирую следующий код (используя g++ 4.0.1)...
class Foo
{
public:
Foo() {};
Foo(int a) {};
void bar() {};
};
int main()
{
// это работает...
Foo foo1(1);
foo1.bar();
// это не работает...
Foo foo2();
foo2.bar();
return 0;
}
... я получаю следующую ошибку:
nonclass.cpp: In function ‘int main(int, const char**)’:
nonclass.cpp:17: error: request for member ‘bar’ in ‘foo2’, which is of non-class type ‘Foo ()()’
Почему это происходит и как мне сделать так, чтобы это работало?
5 ответ(ов)
Вы получаете ошибку, потому что компилятор интерпретирует строку
Foo foo2();
как декларацию функции с именем foo2
, возвращающей тип Foo
.
Однако, если мы изменим строку на Foo foo2
, компилятор может выдать ошибку "call of overloaded ‘Foo()’ is ambiguous"
.
Это происходит потому, что компилятор теперь рассматривает foo2
как объект переменной, а не как функцию. Возможно, у вас есть перегруженный конструктор для типа Foo
, и компилятор не может однозначно определить, какой конструктор вызвать.
Чтобы избежать этих ошибок, вам нужно определиться, хотите ли вы объявить функцию или переменную. Если вы хотите объявить переменную, вы можете просто избавиться от круглых скобок:
Foo foo2; // Теперь это переменная, а не декларация функции
Таким образом, все будет работать корректно, и вы избежите неоднозначности.
Просто для справки...
Это не решение вашей проблемы, но я столкнулся с аналогичным сообщением об ошибке, когда неправильно обращался к методу экземпляра класса, на который указывал myPointerToClass
, например:
MyClass* myPointerToClass = new MyClass();
myPointerToClass.aMethodOfThatClass();
где
myPointerToClass->aMethodOfThatClass();
безусловно, было бы правильным вариантом.
В русском стиле ответа на StackOverflow.com это можно перевести так:
Создание объекта класса без использования круглых скобок не требуется, если вы не планируете использовать параметризованный конструктор.
Просто используйте Foo foo2;
Это сработает.
Добавляю к базе знаний: я столкнулся с такой же ошибкой при использовании кода
if(class_iter->num == *int_iter)
Несмотря на то что IDE правильно подсказывала члены для class_iter
, проблема заключалась в том, что iterator
не имеет члена с именем num
, поэтому мне нужно было разыменовать указатель. Однако это не сработало в таком виде:
if(*class_iter->num == *int_iter)
...очевидно. В итоге я решил проблему следующим образом:
if((*class_iter)->num == *int_iter)
Надеюсь, это поможет кому-то, кто столкнется с этой проблемой так же, как и я.
Похоже, что ошибка, с которой вы столкнулись, связана с тем, что компилятор неправильно интерпретирует вызов конструктора без аргументов. Я успешно решил эту проблему, убрав скобки из объявления переменной. В вашем коде это будет выглядеть так:
class Foo
{
public:
Foo() {};
Foo(int a) {};
void bar() {};
};
int main()
{
// это работает...
Foo foo1(1);
foo1.bar();
// это не работает...
Foo foo2; // Без "()"
foo2.bar();
return 0;
}
Таким образом, чтобы избежать проблемы, просто не используйте круглые скобки при создании экземпляра класса, если вы хотите вызвать конструктор без аргументов.
Что такое Правило трёх?
Разница между const int*, const int * const и int * const?
Имеют ли круглые скобки после имени типа значение при использовании new?
Как удалить элемент из std::vector<> по индексу?
`unsigned int` против `size_t`: когда и что использовать?