我有一个带有两个构造函数的类,一个不带参数,一个带一个参数。
使用带有一个参数的构造函数创建对象可以按预期工作。但是,如果我使用不带参数的构造函数创建对象,则会收到错误。
例如,如果我编译此代码(使用 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 ()()’
这是为什么,我该如何让它发挥作用?
Foo foo2();
更改为
Foo foo2;
你得到错误是因为编译器认为
Foo foo2()
自名称为“foo2”且返回类型为“Foo”的函数声明开始。
但在这种情况下,如果我们更改为
Foo foo2
,编译器可能会显示错误 " call of overloaded ‘Foo()’ is ambiguous"
。
仅供记录..
它实际上不是您代码的解决方案,但是当我错误地访问
myPointerToClass
指向的类实例的方法时,我收到了相同的错误消息,例如
MyClass* myPointerToClass = new MyClass();
myPointerToClass.aMethodOfThatClass();
哪里
myPointerToClass->aMethodOfThatClass();
显然是正确的。
当您不打算使用参数化构造函数时,实例化类对象时不需要括号。
只需使用 Foo foo2;
它会起作用的。
添加到知识库后,我遇到了同样的错误
if(class_iter->num == *int_iter)
尽管 IDE 为我提供了正确的 class_iter 成员。显然,问题是
"anything"::iterator
没有名为 num
的成员,所以我需要取消引用它。这不行:
if(*class_iter->num == *int_iter)
...显然。我最终用这个解决了这个问题:
if((*class_iter)->num == *int_iter)
我希望这可以帮助像我一样遇到这个问题的人。
我遇到了类似的错误,编译器似乎误解了对不带参数的构造函数的调用。我通过从变量声明中删除括号来使其工作,在您的代码中如下所示:
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;
}
我遇到了一个案例,我收到了错误消息并且有
Foo foo(Bar());
并且基本上尝试将临时 Bar 对象传递给 Foo 构造函数。结果编译器将其翻译为
Foo foo(Bar(*)());
也就是说,一个名为 foo 的函数声明返回一个接受参数的 Foo ——一个返回带有 0 个参数的 Bar 的函数指针。当传递这样的临时变量时,最好使用
Bar{}
而不是 Bar()
来消除歧义。
如果你想声明一个没有参数的新物质(知道该对象有默认参数),不要写
type substance1();
但是
type substance;
当然是此错误的一个极端情况,但我在尝试超载作业时在不同的情况下收到了它
operator=
。 在我看来,这有点神秘(来自 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”和我的成员变量data
。 当我将其更改为 void operator=(T newData)
和 data.i = newData;
、data.f = newData;
时,错误消失了。
@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;
}
我刚刚在 Arduino 编程中遇到了这个错误,最终发现接收新值(连接)的变量必须是 String 类型:
myvariable.concat(originalvalue);
所以原始值可以是任何类型,但 myvariable 必须是字符串。