使用参数调用 class 构造函数 - 'x' 中非 class 类型的成员的请求
Calling class constructor with parameter - request of a member in 'x' which is of non-class type
我有一个 class A 接受 class B 作为构造函数参数。 Class B 可以从 int 值构造。我的原始代码非常复杂,但我希望我已将其简化为最基本的情况:
class B {
public:
explicit B(int a) : val(a) {}
private:
int val;
};
class A {
public:
A(const B & val) : value(val) {};
void print() {
//does nothing
}
private:
B value;
};
int main() {
int someTimeVar = 22;
A a(B(someTimeVar));
a.print();
}
这是我收到的错误代码:
$ g++ test.cpp -Wall -O0
test.cpp: In function ‘int main()’:
test.cpp:22:7: error: request for member ‘print’ in ‘a’, which is of non-class type ‘A(B)’
a.print();
^
test.cpp:20:9: warning: unused variable ‘someTimeVar’ [-Wunused-variable]
int someTimeVar = 22;
^
我使用 GCC (4.9.2 20150304 (prerelease)),平台:arch linux.
对 main 函数的以下修改编译正常:
int main() {
A a(B(22));
a.print();
}
我很清楚使用 A a();声明一个函数,而不是一个对象。但是我没想到 A a(B(some_val)) 也会这样做,我认为这就是这里发生的事情。
您知道为什么会这样吗?
编辑:感谢您的所有回答,看来我需要更多地研究最令人烦恼的解析想法。
顺便说一句,事实证明使用 clang 编译我的代码提供了更有用的错误消息和解决方案:
$ clang test.cpp
test.cpp:21:8: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse]
A a(B(someTimeVar));
^~~~~~~~~~~~~~~~
test.cpp:21:9: note: add a pair of parentheses to declare a variable
A a(B(someTimeVar));
^
( )
test.cpp:22:6: error: member reference base type 'A (B)' is not a structure or union
a.print();
~^~~~~~
1 warning and 1 error generated.
A a(B(someTimeVar))
被解释为 A a(B someTimeVar)
,因此 a
是一个接受类型 B
参数并返回 A
.
的函数
这是将统一初始化添加到 C++11 的原因之一:
A a{B{someTimeVar}};
这个问题在 Whosebug 上有自己的标签。最令人烦恼的解析
维基百科对问题及其解决方案有清晰的描述。 https://en.wikipedia.org/wiki/Most_vexing_parse.
The line
TimeKeeper time_keeper(Timer());
could be disambiguated either as
- a variable definition for variable time_keeper of class TimeKeeper, passed an anonymous instance of class Timer or
- a function declaration for a function time_keeper which returns an object of type TimeKeeper and has a single (unnamed) parameter which
is a function returning type Timer (and taking no input). (See
Function object#In C and C++)
Most programmers expect the first, but the C++ standard requires it to
be interpreted as the second.
解决方案是在参数中添加括号,例如:
A a( (B(22)) );
或者像其他人所说的那样使用通用初始化,例如
A a { B{22} };
A a(B(someTimeVar));
声明了一个 return 类型 A 和一个名为 someTimeVar 的 B 类型参数的函数。与 A a(B someTimeVar);
相同
它在 A a(B(22));
中有效,因为 22 不是有效的标识符,因此函数声明将无效。
如果您的代码库使用 C++11(或更新版本),您可以使用带花括号的统一初始化:A a(B{someTimeVar});
我有一个 class A 接受 class B 作为构造函数参数。 Class B 可以从 int 值构造。我的原始代码非常复杂,但我希望我已将其简化为最基本的情况:
class B {
public:
explicit B(int a) : val(a) {}
private:
int val;
};
class A {
public:
A(const B & val) : value(val) {};
void print() {
//does nothing
}
private:
B value;
};
int main() {
int someTimeVar = 22;
A a(B(someTimeVar));
a.print();
}
这是我收到的错误代码:
$ g++ test.cpp -Wall -O0
test.cpp: In function ‘int main()’:
test.cpp:22:7: error: request for member ‘print’ in ‘a’, which is of non-class type ‘A(B)’
a.print();
^
test.cpp:20:9: warning: unused variable ‘someTimeVar’ [-Wunused-variable]
int someTimeVar = 22;
^
我使用 GCC (4.9.2 20150304 (prerelease)),平台:arch linux.
对 main 函数的以下修改编译正常:
int main() {
A a(B(22));
a.print();
}
我很清楚使用 A a();声明一个函数,而不是一个对象。但是我没想到 A a(B(some_val)) 也会这样做,我认为这就是这里发生的事情。
您知道为什么会这样吗?
编辑:感谢您的所有回答,看来我需要更多地研究最令人烦恼的解析想法。
顺便说一句,事实证明使用 clang 编译我的代码提供了更有用的错误消息和解决方案:
$ clang test.cpp
test.cpp:21:8: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse]
A a(B(someTimeVar));
^~~~~~~~~~~~~~~~
test.cpp:21:9: note: add a pair of parentheses to declare a variable
A a(B(someTimeVar));
^
( )
test.cpp:22:6: error: member reference base type 'A (B)' is not a structure or union
a.print();
~^~~~~~
1 warning and 1 error generated.
A a(B(someTimeVar))
被解释为 A a(B someTimeVar)
,因此 a
是一个接受类型 B
参数并返回 A
.
这是将统一初始化添加到 C++11 的原因之一:
A a{B{someTimeVar}};
这个问题在 Whosebug 上有自己的标签。最令人烦恼的解析
维基百科对问题及其解决方案有清晰的描述。 https://en.wikipedia.org/wiki/Most_vexing_parse.
The line
TimeKeeper time_keeper(Timer());
could be disambiguated either as
- a variable definition for variable time_keeper of class TimeKeeper, passed an anonymous instance of class Timer or
- a function declaration for a function time_keeper which returns an object of type TimeKeeper and has a single (unnamed) parameter which is a function returning type Timer (and taking no input). (See Function object#In C and C++)
Most programmers expect the first, but the C++ standard requires it to be interpreted as the second.
解决方案是在参数中添加括号,例如:
A a( (B(22)) );
或者像其他人所说的那样使用通用初始化,例如
A a { B{22} };
A a(B(someTimeVar));
声明了一个 return 类型 A 和一个名为 someTimeVar 的 B 类型参数的函数。与 A a(B someTimeVar);
它在 A a(B(22));
中有效,因为 22 不是有效的标识符,因此函数声明将无效。
如果您的代码库使用 C++11(或更新版本),您可以使用带花括号的统一初始化:A a(B{someTimeVar});