【问题标题】:Pointer to member function syntax指向成员函数语法的指针
【发布时间】:2016-12-27 15:49:42
【问题描述】:

我正试图围绕指向成员函数的指针转转,并坚持使用这个示例:

#include <iostream>

class TestClass {
  public:
    void TestMethod(int, int) const;
};

void TestClass::TestMethod(int x, int y) const {
  std::cout << x << " + " << y << " = " << x + y << std::endl;
}

int main() {
  void (TestClass::*func)(int, int) const;
  func = TestClass::TestMethod;

  TestClass tc;
  tc.func(10, 20);

  return 0;
}

我认为代码应该做什么:

  • 在 main 的第一行我声明了一个指向 class TestClass 的成员函数的指针,它什么都不返回/接受两个 int 并声明为 const,称为 func
  • 第二行将成员函数 TestMethod(属于 TestClass 类)分配给满足这些条件的 func
  • 第四行创建了一个名为tcTestClass-object。
  • 第五行尝试在TestClass-object tc上调用func指向的成员函数。

我得到两个编译错误:

  • 而不是将TestClass::TestMethod 分配给func。编译器尝试调用TestClass::TestMethod(即使它不是static,因此会抛出错误):

    testPointerToMemberFunc.cpp:14:21: error: call to non-static member function without an object argument
      func = TestClass::TestMethod;
             ~~~~~~~~~~~^~~~~~~~~~
    
  • 编译器尝试在tc 上调用名为func 的函数,而不是func 指向的函数。对我来说,这似乎就像 func 没有以正确的方式声明(作为指向成员函数的指针):

    testPointerToMemberFunc.cpp:17:6: error: no member named 'func' in 'TestClass'
      tc.func(10, 20);
      ~~ ^
    

我做错了什么?

【问题讨论】:

    标签: c++ class pointers member-function-pointers member-functions


    【解决方案1】:

    简单的语法细节。

    func = &TestClass::TestMethod;
    //     ^ Missing ampersand to form a pointer-to-member
    
    TestClass tc;
    (tc.*func)(10, 20);
    // ^^ Using the dot-star operator to dereference the pointer-to-member,
    // while minding its awkward precedence with respect to the call operator.
    

    【讨论】:

    • 你知道1. 为什么我需要显式地取函数的地址(我不需要这样做,对于正常 函数指针)?还有 2. 为什么我需要显式取消引用指针(我不需要这样做,使用 normal 函数指针)?
    • @Herickson 恐怕“因为标准这么说”就是答案。形成指向成员的指针有一个固定的语法,它是&amp;A::b(即使&amp;(A::b) 也没有删减它)。 .* 不是一个点运算符后跟一个取消引用运算符,而是一个取消引用指向成员的指针的单个运算符。点运算符仅适用于其右侧的成员名称。
    【解决方案2】:

    func = TestClass::TestMethod; 应该是func = &amp;TestClass::TestMethod;tc.func(10, 20) 应该是(tc.*func)(10, 20)(在后者中,请注意有两个变化:. 变为.*,并且有加了括号;两者都是必需的)。

    【讨论】:

    • 你知道1. 为什么我需要显式地取函数的地址(我不需要这样做,对于正常 函数指针)?还有 2. 为什么我需要显式取消引用指针(我不需要这样做,使用 normal 函数指针)?
    • @Herickson:常规函数的行为方式类似于指向函数的指针,反之亦然,是从 C 继承的。由于 C 不支持指向成员的指针,因此这些函数没有必要在 C++ 中以这种方式工作。
    • @VaughnCato 谢谢,所以我不能真正将普通函数指针与指向成员函数的指针进行比较?
    • @Herickson:不,它们非常不同。
    【解决方案3】:

    指向成员(函数或其他)的指针与常规指针非常不同,尽管在语法上有一些相似之处。常规函数的行为方式类似于指向函数的指针,反之亦然,是从 C 继承的,但 C 不支持指向成员的指针,因此在 C++ 中没有必要以这种方式工作。

    要创建一个指向成员的指针,你必须显式使用&amp;,并且你必须显式使用.* 来间接它,如果你不习惯函数的方式,这可能是你所期望的更多在 C 中工作:

    func = &TestClass::TestMethod;
    (tc.*func)(10, 20);
    

    【讨论】:

      猜你喜欢
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多