提问者:小点点

关于使用auto进行成员函数指针类型推断的问题


我的问题是关于成员函数指针的。这里有一个示例代码:类继承,从继承。我原以为是同一类型的,但实际上它们是不同类型的,一个是,另一个是。我使用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;
}

共2个答案

匿名用户

是的,这是标准规定的:

当您有一个从其他类继承的类时,那些类的成员不是派生类的成员。它们仍然是其类的成员,派生类继承它们。所以,的成员仍然是的成员,这仍然反映在它们的类型中。这几乎是C++的一个核心原则,您只是在实际操作中观察到了这一点。

就像当你把一堆书放在你的书架上时,那些书中的章节并没有成为书架的一部分。它们仍然是书中相同的章节,你的书架就是存取它们的手段。

类似地,您可以使用访问其父类的成员,使用类的名称。但它们仍然是的成员,这反映在它们的类型中。

当使用use时,您将获得表达式的确切类型。C++允许您将指向基类成员的指针转换为指向派生类成员的指针。然而,这是一种转换。使用时不会发生转换,因为这正是的作用:使用表达式的任何实际类型来初始化/构造对象,而不进行任何转换(这里有一些关于引用的精细细节,增加了一些曲折,但与本文讨论无关)。

匿名用户

这种选择背后的基本原理是这样一个事实:对一种类型的假设越少,它就越好。

是一个,因此是从a继承的成员函数的最通用类型。

你为什么要强制执行一个更严格的类型?这是一个双赢的局面。