错误:请求'..'中的成员'..',这是非类型的

时间:2009-05-18 12:38:30

标签: c++

我有一个带有两个构造函数的类,一个不带参数,另一个带一个参数。

使用带有一个参数的构造函数创建对象可以按预期工作。但是,如果我使用不带参数的构造函数创建对象,我会收到错误。

例如,如果我编译此代码(使用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 个答案:

答案 0 :(得分:592)

Foo foo2();

更改为

Foo foo2;

您收到错误,因为编译器认为

Foo foo2()

从函数声明开始,名称为'foo2',返回类型为'Foo'。

但在这种情况下,如果我们更改为Foo foo2,编译器可能会显示错误" call of overloaded ‘Foo()’ is ambiguous"

答案 1 :(得分:37)

仅供记录..

它实际上不是您的代码的解决方案,但是当我错误地访问myPointerToClass指向的类实例的方法时,我有相同的错误消息,例如

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

,其中

myPointerToClass->aMethodOfThatClass();

显然是正确的。

答案 2 :(得分:4)

我遇到了类似的错误,似乎编译器误解了没有参数的构造函数的调用。我通过在代码中删除变量声明中的括号使其工作:

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

答案 3 :(得分:4)

当您不打算使用参数化构造函数时,不需要使用括号来实例化类对象。

只需使用 Foo foo2;

它会起作用。

答案 4 :(得分:2)

我遇到了一个案例,我收到了错误消息并且

Foo foo(Bar());

并且基本上是尝试将临时Bar对象传递给Foo构造函数。事实证明编译器正在将其转换为

Foo foo(Bar(*)());

,即一个名为foo的函数声明,它返回一个接受参数的Foo - 一个返回带有0个参数的Bar的函数指针。传递这样的临时对象时,最好使用Bar{}代替Bar()来消除歧义。

答案 5 :(得分:0)

如果你想声明一个没有参数的新物质(知道对象有默认参数)不要写

 type substance1();

 type substance;

答案 6 :(得分:0)

在某些情况下肯定会出现此错误,但是在尝试使分配(B)重载时,我在另一种情况下收到了此错误。这是一个有点神秘的IMO(来自g ++ 8.1.1)。

operator=

我收到2个“完全相同”的错误

#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;
}

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 uniondata.i = data;。事实证明,编译器使局部变量名称“ data”和我的成员变量data.f = data;混淆了。当我将其更改为datavoid operator=(T newData)data.i = newData;时,错误消失了。

答案 7 :(得分:0)

@MykolaGolubyev已经给出了很好的解释。我一直在寻找一种解决方案,例如MyClass obj ( MyAnotherClass() ),但编译器将其解释为函数声明。

C ++ 11具有braced-init-list。使用这个我们可以做这样的事情

Temp t{String()};

但是,这:

Temp t(String());

认为t类型为Temp(String (*)())时抛出编译错误。

#include <iostream>

class String {
public:
    String(const char* str): ptr(str)
    {
        std::cout << "Constructor: " << str << std::endl;
    }
    String(void): ptr(nullptr)
    {
        std::cout << "Constructor" << std::endl;
    }
    virtual ~String(void)
    {
        std::cout << "Destructor" << std::endl;
    }

private:
    const char *ptr;
};

class Temp {
public:
    Temp(String in): str(in)
    {
        std::cout << "Temp Constructor" << std::endl;
    }

    Temp(): str(String("hello"))
    {
        std::cout << "Temp Constructor: 2" << std::endl;
    }
    virtual ~Temp(void)
    {
        std::cout << "Temp Destructor" << std::endl;
    }

    virtual String get_str()
    {
        return str;
    }

private:
    String str;
};

int main(void)
{
    Temp t{String()}; // Compiles Success!
    // Temp t(String()); // Doesn't compile. Considers "t" as of type: Temp(String (*)())
    t.get_str(); // dummy statement just to check if we are able to access the member
    return 0;
}