ошибка: запрос на член '..' в '..', который не является типом класса - PullRequest
390 голосов
/ 18 мая 2009

У меня есть класс с двумя конструкторами, один из которых не имеет аргументов, а другой - один аргумент.

Создание объектов с использованием конструктора, который принимает один аргумент, работает как ожидалось. Однако, если я создаю объекты, используя конструктор, который не принимает аргументов, я получаю сообщение об ошибке.

Например, если я скомпилирую этот код (используя g ++ 4.0.1) ...

class Foo
{
  public:
    Foo() {};
    Foo(int a) {};
    void bar() {};
};

int main()
{
  // this works...
  Foo foo1(1);
  foo1.bar();

  // this does not...
  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 ()()’

Почему это так и как мне заставить это работать?

Ответы [ 8 ]

597 голосов
/ 18 мая 2009
Foo foo2();

изменить на

Foo foo2;

Вы получаете ошибку, потому что компилятор думает о

Foo foo2()

с момента объявления функции с именем 'foo2' и типом возврата 'Foo'.

Но в этом случае, если мы изменим на Foo foo2, компилятор может показать ошибку " call of overloaded ‘Foo()’ is ambiguous".

37 голосов
/ 05 марта 2013

Только для записи ..

На самом деле это не решение вашего кода, но у меня было то же сообщение об ошибке при неправильном доступе к методу экземпляра класса, на который указывает myPointerToClass, например

MyClass* myPointerToClass = new MyClass();
myPointerToClass.aMethodOfThatClass();

где

myPointerToClass->aMethodOfThatClass();

очевидно будет правильным.

9 голосов
/ 12 февраля 2014

При добавлении в базу знаний я получил ту же ошибку за

if(class_iter->num == *int_iter)

Несмотря на то, что в среде IDE были указаны правильные члены для class_iter. Очевидно, проблема в том, что "anything"::iterator не имеет члена с именем num, поэтому мне нужно разыменовать его. Который не работает так:

if(*class_iter->num == *int_iter)

... видимо. В конце концов я решил это с помощью:

if((*class_iter)->num == *int_iter)

Надеюсь, это поможет тому, кто сталкивается с этим вопросом, как я.

4 голосов
/ 01 августа 2017

Скобки не требуются для создания экземпляра объекта класса, если вы не собираетесь использовать параметризованный конструктор.

Просто используйте Foo foo2;

Это будет работать.

4 голосов
/ 09 марта 2015

У меня была похожая ошибка, похоже, что компилятор неправильно понял вызов конструктора без аргументов. Я сделал это, убрав круглые скобки из объявления переменной, в вашем коде что-то вроде этого:

class Foo
{
  public:
    Foo() {};
    Foo(int a) {};
    void bar() {};
};

int main()
{
  // this works...
  Foo foo1(1);
  foo1.bar();

  // this does not...
  Foo foo2; // Without "()" 
  foo2.bar();

  return 0;
}
2 голосов
/ 07 сентября 2017

Я столкнулся с случаем, когда я получил это сообщение об ошибке и имел

Foo foo(Bar());

и в основном пытался передать временный объект Bar конструктору Foo. Оказывается, компилятор переводил это на

Foo foo(Bar(*)());

то есть объявление функции, чье имя foo возвращает Foo, принимающий аргумент - указатель функции, возвращающий Bar с 0 аргументами При прохождении временных темпов, подобных этому, лучше использовать Bar{} вместо Bar() для устранения неоднозначности.

0 голосов
/ 12 августа 2018

Конечно, угловой случай для этой ошибки, но я получил ее в другой ситуации, когда пытался перегрузить присвоение operator=. Это было немного загадочно IMO (из g ++ 8.1.1).

#include <cstdint>

enum DataType
{
  DT_INT32,
  DT_FLOAT
};

struct PrimitiveData
{
  union MyData
  {
    int32_t i;
    float f;
  } data;

  enum DataType dt;

  template<typename T>
  void operator=(T data)
  {
    switch(dt)
    {
      case DT_INT32:
      {
        data.i = data;
        break;
      }
      case DT_FLOAT:
      {
        data.f = data;
        break;
      }
      default:
      {
        break;
      }
    }
  }
};

int main()
{
  struct PrimitiveData pd;
  pd.dt = DT_FLOAT;
  pd = 3.4f;

  return 0;
}

Я получил 2 "идентичные" ошибки

error: request for member ‘i’ [and 'f'] in ‘data’, which is of non-class type ‘float’

(Эквивалентная ошибка для clang: error: member reference base type 'float' is not a structure or union)

для строк data.i = data; и data.f = data;. Оказывается, компилятор путал имя локальной переменной 'data' и мою переменную-член data. Когда я изменил это значение на void operator=(T newData) и data.i = newData;, data.f = newData;, ошибка исчезла.

0 голосов
/ 08 февраля 2018

Если вы хотите объявить новое вещество без параметров (зная, что у объекта есть параметры по умолчанию), не пишите

 type substance1();

но

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