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

使用带一个参数的构造函数创建对象可以正常工作。但是,如果我使用不带参数的构造函数创建对象,就会得到一个错误。

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

为什么会这样,我该怎么做呢?


当前回答

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

 type substance1();

but

 type substance;

其他回答

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

 type substance1();

but

 type substance;

@MykolaGolubyev已经给出了精彩的解释。我正在寻找一个解决方案来做这样的MyClass obj (MyAnotherClass()),但编译器将其解释为函数声明。

c++ 11有括号-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;
}

当然是这个错误的极端情况,但我在不同的情况下收到它,当我试图重载赋值操作符=时。在我看来,它有点神秘(来自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的等效误差为: 错误:成员引用基类型'float'不是结构体或并体)

对于行数据。I =数据;和数据。F =数据;。原来编译器混淆了局部变量名称“数据”和我的成员变量数据。当我把这个改为void operator=(T newData)和data。i = newData;, data。f = newData;,错误消失。

我遇到了这样的情况,我得到了错误信息

Foo foo(Bar());

基本上是试图将一个临时的Bar对象传递给Foo构造函数。结果是编译器把这个翻译成

Foo foo(Bar(*)());

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

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

只需使用Foo foo2;

它会起作用的。