I have a class with two constructors, one that takes no arguments and one that takes one argument.
Creating objects using the constructor that takes one argument works as expected. However, if I create objects using the constructor that takes no arguments, I get an error.
For instance, if I compile this code (using 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;
}
... I get the following error:
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 ()()’
Why is this, and how do I make it work?
This question is related to
c++
Parenthesis is not required to instantiate a class object when you don't intend to use a parameterised constructor.
Just use Foo foo2;
It will work.
@MykolaGolubyev has already given wonderful explanation. I was looking for a solution to do somthing like this MyClass obj ( MyAnotherClass() )
but the compiler was interpreting it as a function declaration.
C++11 has braced-init-list. Using this we can do something like this
Temp t{String()};
However, this:
Temp t(String());
throws compilation error as it considers t
as of type 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;
}
I ran into a case where I got that error message and had
Foo foo(Bar());
and was basically trying to pass in a temporary Bar object to the Foo constructor. Turns out the compiler was translating this to
Foo foo(Bar(*)());
that is, a function declaration whose name is foo that returns a Foo that takes in an argument -- a function pointer returning a Bar with 0 arguments. When passing in temporaries like this, better to use Bar{}
instead of Bar()
to eliminate ambiguity.
I was having a similar error, it seems that the compiler misunderstand the call to the constructor without arguments. I made it work by removing the parenthesis from the variable declaration, in your code something like this:
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;
}
Adding to the knowledge base, I got the same error for
if(class_iter->num == *int_iter)
Even though the IDE gave me the correct members for class_iter. Obviously, the problem is that "anything"::iterator
doesn't have a member called num
so I need to dereference it. Which doesn't work like this:
if(*class_iter->num == *int_iter)
...apparently. I eventually solved it with this:
if((*class_iter)->num == *int_iter)
I hope this helps someone who runs across this question the way I did.
If you want to declare a new substance with no parameter (knowing that the object have default parameters) don't write
type substance1();
but
type substance;
Certainly a corner case for this error, but I received it in a different situation, when attempting to overload the assignment operator=
. It was a bit cryptic IMO (from 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;
}
I received 2 "identical" errors
error: request for member ‘i’ [and 'f'] in ‘data’, which is of non-class type ‘float’
(The equivalent error for clang
is:
error: member reference base type 'float' is not a structure or union
)
for the lines data.i = data;
and data.f = data;
. Turns out the compiler was confusing local variable name 'data' and my member variable data
. When I changed this to void operator=(T newData)
and data.i = newData;
, data.f = newData;
, the error went away.
Just for the record..
It is actually not a solution to your code, but I had the same error message when incorrectly accessing the method of a class instance pointed to by myPointerToClass
, e.g.
MyClass* myPointerToClass = new MyClass();
myPointerToClass.aMethodOfThatClass();
where
myPointerToClass->aMethodOfThatClass();
would obviously be correct.
Source: Stackoverflow.com