我有一个带有两个构造函数的类,一个不带参数,另一个带一个参数。
使用带有一个参数的构造函数创建对象可以按预期工作。但是,如果我使用不带参数的构造函数创建对象,我会收到错误。
例如,如果我编译此代码(使用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 ()()’
为什么会这样,我该如何使它发挥作用?
答案 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 union
和data.i = data;
。事实证明,编译器使局部变量名称“ data”和我的成员变量data.f = data;
混淆了。当我将其更改为data
和void 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;
}