【问题标题】:error: request for member '..' in '..' which is of non-class type错误:在非类类型的“..”中请求成员“..”
【发布时间】:2010-10-27 00:36:15
【问题描述】:

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

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

例如,如果我编译这段代码(使用 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 ()()’

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

【问题讨论】:

标签: c++


【解决方案1】:
Foo foo2();

改成

Foo foo2;

你得到错误是因为编译器认为

Foo foo2()

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

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

【讨论】:

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

只是为了记录..

这实际上不是你的代码的解决方案,但是当我错误地访问myPointerToClass指向的类实例的方法时,我得到了同样的错误信息,例如

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

在哪里

myPointerToClass->aMethodOfThatClass();

显然是正确的。

【讨论】:

    【解决方案3】:

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

    只需使用 Foo foo2;

    它会起作用的。

    【讨论】:

      【解决方案4】:

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

      if(class_iter->num == *int_iter)
      

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

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

      ...显然。我最终解决了这个问题:

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

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

      【讨论】:

        【解决方案5】:

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

        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] 之间,该标准明确规定,如果出现歧义,任何可以解释为声明的内容都是声明,以解决这种歧义。)跨度>
        【解决方案6】:

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

        Foo foo(Bar());
        

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

        Foo foo(Bar(*)());
        

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

        【讨论】:

          【解决方案7】:

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

           type substance1();
          

          但是

           type substance;
          

          【讨论】:

            【解决方案8】:

            这个错误肯定是一个极端情况,但我在不同的情况下收到它,当我试图重载分配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; 时,错误消失了。

            【讨论】:

              【解决方案9】:

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2019-04-28
                • 2018-02-11
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多