Reputation: 13
I wonder if anybody can help with what seems to me like strange behaviour in c++
(gcc
latest version). Below is some code that compiles successfully where I would expect a compile time error due to the lack of an appropriate constructor. Can anybody explain what is going on?
#include <iostream>
using namespace std;
struct ClassA {
ClassA() {cout << "hello" << endl;}
void speak() {cout << "I am class A" << endl;}
~ClassA() {cout << "goodbye" << endl;}
};
struct ClassB {
// just an empty struct
};
int main() {
ClassA myClassA(ClassB()); // trying to construct class A from an rvalue reference to class B is ok?
return 0;
}
}
If I try to call a function of class A
, I do get a compile time error:
int main() {
ClassA myClassA(ClassB());
myClassA.speak();
return 0;
}
results in:
error: request for member ‘speak’ in ‘myClassA', which is of non-class type ‘ClassA(ClassB (*)())’
Thanks!
Upvotes: 1
Views: 115
Reputation: 11
This is a situation called the Most Vexing Parse.
First and formost, ClassB
does have a constructor. When you don't create one of your own the compiler provides one for you. And on the line where you passed an instance of ClassB
into what seems like a valid copy construction, what actually happens is that the line is evaluated as the declaration of a function that returns an instance of ClassA
and takes an anonymous instance of ClassB
.
Upvotes: 1
Reputation: 110738
ClassA myClassA(ClassB());
declares a function called myClassA
that returns a ClassA
and takes one argument which is a pointer to a function that returns a ClassB
and takes no arguments. This is the most vexing parse.
Upvotes: 1
Reputation: 477464
You're never declaring an object at all. Instead, you've declared a function, and so there's no constructor needed at all. (Note that ClassB()
denotes a function type!)
If you want to construct an object from a temporary, try one of these syntaxes:
ClassA x1 { ClassB{} }; // C++11 only
ClassA x2((ClassB())); // parenthesized expression is never a type declaration
Upvotes: 3