ChatGPT解决这个技术问题 Extra ChatGPT

错误:在非类类型的“..”中请求成员“..”

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 ()()’

为什么会这样,我该如何让它发挥作用?


E
Edward Karak
Foo foo2();

改成

Foo foo2;

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

Foo foo2()

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

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


我不明白为什么编译器认为: Foo foo2() 作为函数声明,在主函数内部。
显然我之前已经得到了这个答案,因为我不能再投票了!这是文字的第二次赞成……第二次感谢!
无参数函数声明应该强制使用“void”参数,以便从一致性的角度来看允许这种用法。如果我没记错的话,K&R C 强制使用术语 void。
@Rajesh:空参数列表不是强制性的,它只是意味着与空参数列表(未指定的参数)不同的东西(零参数)。
这是切换到 c++11 中引入的 uniform {} initialization syntax 的另一个好理由
m
metamorphosis

只是为了记录..

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

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

在哪里

myPointerToClass->aMethodOfThatClass();

显然是正确的。


R
Reena Cyril

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

只需使用 Foo foo2;

它会起作用的。


M
Matt

添加到知识库中,我得到了同样的错误

if(class_iter->num == *int_iter)

即使 IDE 为我提供了 class_iter 的正确成员。显然,问题在于 "anything"::iterator 没有名为 num 的成员,因此我需要取消引用它。这不是这样工作的:

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

...显然。我最终用这个解决了它:

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

我希望这可以帮助像我一样遇到这个问题的人。


A
Alexis Lopez Zubieta

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

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

这与 the one above 的答案相同
most vexing parse 并没有让编译器误解,因为标准要求编译器将任何可能是函数声明的内容解释为函数声明,以防止歧义。
(具体而言,在 [stmt.ambig/1][dcl.ambig.res/1] 之间,该标准明确规定,在出现歧义的情况下,任何可以解释为声明的内容都是声明,以解决该歧义。)
s
solstice333

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

Foo foo(Bar());

并且基本上试图将临时 Bar 对象传递给 Foo 构造函数。原来编译器正在将其翻译为

Foo foo(Bar(*)());

也就是说,一个名为 foo 的函数声明,它返回一个 Foo ,它接受一个参数——一个函数指针,返回一个带 0 个参数的 Bar 。像这样传入临时对象时,最好使用 Bar{} 而不是 Bar() 来消除歧义。


y
yano

这个错误肯定是一个极端情况,但是当我尝试重载赋值 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。当我将其更改为 void operator=(T newData)data.i = newData;data.f = newData; 时,错误消失了。


P
Prashant_M

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

 type substance1();

 type substance;

a
abhiarora

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