首页 > 解决方案 > 关于使用auto进行成员函数指针类型推断的问题

问题描述

我的问题是关于成员函数指针。这里有一个示例代码:类C继承fooAbarB. 我预计两者&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;
}

标签: c++c++11

解决方案


是的,这是标准规定的:

当您有一个从其他类继承的类时,这些类的成员不是派生类的成员。它们仍然是其类的成员,派生类继承它们。因此, and 的成员A仍然是 andB的成员,A并且B在适当的情况下,这仍然反映在它们的类型中。这几乎是 C++ 的核心原则,您只是在实际中观察它。

就像你把一堆书放在书架上一样,这些书中的章节不会成为书架的一部分。它们仍然是书中的相同章节,您的书架是访问它们的途径。

同样,您可以使用C它来访问其父类的成员,A并且B,使用类的名称C。但它们仍然是 and 的成员AB这反映在它们的类型中。

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


推荐阅读