功能指针指向孩子与父母
我正在学习C ++,并且我不断遇到一个奇怪的汇编错误。我将代码简化为以下示例:
#include <iostream>
class A {
public:
static A foo()
{
A a;
return a;
}
};
class B : A
{
public:
static B boo()
{
B b;
return b;
}
};
typedef A (*function)(void);
int main() {
function f1 = A::foo;
function f2 = B::boo; //error
return 0;
}
我收到以下错误:
无法用类型为'b()'的lvalue初始化类型'函数'的变量(aka'a(*)()):不同的返回类型('a'vs'vs'b')
任何人都可以解释为什么它不起作用吗?由于b
是a
的孩子, b 是a
,为什么功能指针从“ void到<”代码> b “不像从“ void到a
”的功能指针?
I'm learning C++ and I keep getting a weird compilation error I don't understand. I simplified my code to the following example:
#include <iostream>
class A {
public:
static A foo()
{
A a;
return a;
}
};
class B : A
{
public:
static B boo()
{
B b;
return b;
}
};
typedef A (*function)(void);
int main() {
function f1 = A::foo;
function f2 = B::boo; //error
return 0;
}
I get the following error:
Cannot initialize a variable of type 'function' (aka 'A (*)()') with an lvalue of type 'B ()': different return type ('A' vs 'B')
Would anyone be able to explain why it doesn't work? Since B
is a child of A
, B
is A
, why is a function pointer from "void to B
" isn't like a function pointer from "void to A
"?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
的确,C ++允许指向子类的指针将其转换为指针转换为父类(以某些条件为准)。
确实,C ++允许对子类的引用转换为对父类的引用(也要遵守某些条件)。
但是,这并不意味着C ++允许指向返回父类的函数,将父类转换为指针转换为返回子类的函数。这就是所显示的代码正在尝试执行的操作,这是不允许的。
那回答了您的“为什么”问题:因为在C ++中不允许这样做。至于原因,“为什么”;这主要是由于一些实际的考虑因素,但这并不重要,而C ++的规则不允许。
It is true that C++ allows a pointer to a child class to get converted to a pointer to the parent class (subject to certain conditions).
It is also true that C++ allows a reference to a child class to get converted to a reference to the parent class (also subject to certain conditions).
However, that does not mean that C++ allows a pointer to a function that returns a parent class to be converted to a pointer to a function that returns the child class. This is what the shown code is trying to do, and that is not allowed.
That answer your question of "why": because this is not allowed in C++. As far as why, the "why"; that's mostly due to some practical considerations, but that's immaterial, that's just not allowed by the rules of C++.
您的
函数
声明它应该返回a
但boo
返回ab
,所以:您可以解决它通过从这两个函数中返回基类指针:
或者更好,使用智能指针不必手动删除实例:
Your
function
claims that it should return anA
butboo
returns aB
, so:You could possibly solve it by returning a base class pointer from both functions:
Or better, using smart pointers to not have to
delete
instances manually:而不是完全。由于
b
是a
的孩子,因此任何b
对象也是a
对象。但是,这不是对称的,因此声称b
是a
的情况正在夸大案例。声称“ ab
是a
>”是正确的,但是删除无限期的文章(“ a”和“ an an”)是错误的。因为
b
不是a
。返回类型不同,因此功能类型不同。 AB
可以将对象转换为a
对象(通过复制a
sub-object),但这是一个额外的步骤。如果要编写,则编译器将调用
b
插入a
之后的转换 boo()。转换可能不需要机器说明(又称“ no-op”),但是它仍然存在。 (进行转换的一种副作用是,复制不能为 /a>。)如果您要通过类型
a(*)(*)()()
的功能指针调用boo()
,则没有什么可以告诉编译器插入转换。跳过转换可能是一个问题,尤其是如果b
对象在a
对象中没有数据成员,尤其是当这些数据成员具有非平凡的破坏性器时。该语言不会试图在跳过转换的情况下绘制界限,这不是问题。这同时适用于返回类型和参数类型。分配给指针的函数的类型必须与指针类型完全匹配,不需要转换。
这就是函数对象(例如
std :: function
)的地方很有用。std :: function&lt; a()&gt;
可以存储a:foo
或b :: booo
。这是因为功能对象将适应并记录需要哪些转换,类似于直接调用函数时发生的情况。与功能指针不同,功能对象不需要类型上的确切匹配。Not quite. Since
B
is a child ofA
, anyB
object is also anA
object. However, this is not symmetric, so it is overstating the case to claim thatB
isA
. It is correct to claim "aB
is anA
", but dropping the indefinite articles ("a" and "an") makes the claim false.Because
B
is notA
. The return types are different, so the function types are different. AB
object can be converted to anA
object (by copying theA
sub-object), but that is an extra step. If you were to writethen the compiler inserts a conversion from
B
toA
afterboo()
is called. The conversion might not require machine instructions (a.k.a. a "no-op"), but it is there nonetheless. (One side-effect of having a conversion is that copying cannot be elided.)If you were to invoke
boo()
through a function pointer of the typeA(*)()
, there would be nothing to tell the compiler to insert the conversion. Skipping the conversion could be an issue, particularly if aB
object had data members not inA
objects, especially if those data members had non-trivial destructors.The language does not attempt to draw a line between the cases where skipping the conversion is and is not a problem. This applies to both the return type and the parameter types. The type of a function assigned to a pointer must match the pointer's type exactly, no conversions needed.
This is where function objects, like
std::function
, are useful. Astd::function<A()>
could store eitherA:foo
orB::boo
. This is because the function object will adapt and record what conversions are needed, similar to what happens when invoking a function directly. Unlike a function pointer, a function object does not require an exact match on types.