如何解决关于使用auto进行成员函数指针类型推断的问题
我的问题是关于成员函数指针。这是一个示例代码:
类 C
从 foo
继承 A
,从 bar
继承 B
。
我希望 &C::foo
和 &C::bar
都属于同一类型 void (C::*)()
,
但实际上它们是不同的类型,一种是void(A::*)()
另一个是void(B::*)()
。我使用 gdb ptype 命令来检查
数据类型。
我的问题是:这种行为是由 C++ 标准定义的吗?这个设计决定的基本原理是什么?
#include <type_traits>
#include <iostream>
struct A {
void foo() {
std::cout << this << std::endl;
}
int a;
};
struct B {
void bar() {
std::cout << this << std::endl;
}
int b;
};
struct C : public A,B { };
int main() {
auto p1 = &C::foo; // p1 is void (A::*)();
auto p2 = &C::bar; // p2 is void (B::*)();
auto p3 = &A::foo; // p3 is void (A::*)();
bool b1 = std::is_same<decltype(p1),decltype(p2)>::value;
bool b2 = std::is_same<decltype(p1),decltype(p3)>::value;
std::cout << b1 << std::endl; // false
std::cout << b2 << std::endl; // true
return 0;
}
解决方法
是的,这是标准规定的:
当您有一个从其他类继承的类时,这些类的成员不是派生类的成员。它们仍然是它们的类的成员,并且派生类继承它们。因此,A
和 B
的成员仍然是 A
和 B
的成员,并且这仍然反映在它们的类型中(在适当的情况下)。这几乎是 C++ 的核心原则,您只是在实际中观察它。
就像你把一堆书放在书架上一样,这些书中的章节不会成为书架的一部分。它们仍然是书中的相同章节,您可以通过书架访问它们。
同样,您可以使用 C
访问其父类 A
和 B
的成员,使用类 C
的名称。但它们仍然是 A
和 B
的成员,这反映在它们的类型中。
当使用 use auto
时,您将获得表达式的确切类型。 C++ 允许您将指向基类成员的指针转换为指向派生类成员的指针。但是,这是一种转化。使用 auto
时不会发生转换,因为这正是 auto
的用途:使用表达式的实际类型,初始化/构造对象,并且不进行任何转换(有这里有一些细节,在参考文献方面增加了一些曲折,但这与本次讨论无关)。
这种选择背后的基本原理是,您对一种类型的假设越少,它就越好。
C
是一个 A
,所以 (A::foo*)()
是继承自 A 的成员函数的最通用的类型。
为什么要强制执行更严格的类型?这是一个双赢的局面。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。