指向成员函数的函数指针

发布于 2024-08-31 02:18:22 字数 700 浏览 1 评论 0原文

有几个重复项,但没有人解释为什么我可以使用成员变量来存储指针(在 FOO 中),但是当我尝试使用局部变量时(在 BAR 的注释部分中)),这是非法的。有人能解释一下吗?

#include <iostream>
using namespace std;

class FOO
{
public:
 int (FOO::*fptr)(int a, int b);
 int add_stuff(int a, int b)
 {
  return a+b;
 }
 void call_adder(int a, int b)
 {  
  fptr = &FOO::add_stuff;
  cout<<(this->*fptr)(a,b)<<endl;
 }
};

class BAR
{
public:
 int add_stuff(int a, int b)
 {
  return a+b;
 }
 void call_adder(int a, int b)
 {  
  //int (BAR::*fptr)(int a, int b);
  //fptr = &BAR::add_stuff;
  //cout<<(*fptr)(a,b)<<endl;
 }
};

int main()
{
 FOO test;
 test.call_adder(10,20);
 return 0;
}

There are several duplicates of this but nobody explains why I can use a member variable to store the pointer (in FOO) but when I try it with a local variable (in the commented portion of BAR), it's illegal. Could anybody explain this?

#include <iostream>
using namespace std;

class FOO
{
public:
 int (FOO::*fptr)(int a, int b);
 int add_stuff(int a, int b)
 {
  return a+b;
 }
 void call_adder(int a, int b)
 {  
  fptr = &FOO::add_stuff;
  cout<<(this->*fptr)(a,b)<<endl;
 }
};

class BAR
{
public:
 int add_stuff(int a, int b)
 {
  return a+b;
 }
 void call_adder(int a, int b)
 {  
  //int (BAR::*fptr)(int a, int b);
  //fptr = &BAR::add_stuff;
  //cout<<(*fptr)(a,b)<<endl;
 }
};

int main()
{
 FOO test;
 test.call_adder(10,20);
 return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

浅暮の光 2024-09-07 02:18:22

显然,您误解了 FOO 调用中 this->* 的含义。

当您将 this->* 与成员 fptr 指针一起使用时,this->* 部分与 fptr 完全无关>fptrFOO 的成员。当您使用指向成员的指针调用成员函数时,您必须使用 ->* 运算符(或 .* 运算符),并且您总是 必须指定要与该成员指针一起使用的实际对象。这就是调用表达式的 this->* 部分的作用。即,调用总是看起来像

(<pointer-to-object> ->* <pointer-to-member>) (<arguments>)

或作为

(<object> .* <pointer-to-member>) (<arguments>)

调用的左侧(<指向对象的指针>上述)不能省略。

换句话说,无论fptr是成员变量、局部变量、全局变量还是任何其他类型的变量,通过fptr的调用都会总是看起来像是

(this->*fptr)(a, b);

假设您想使用 *this 对象调用它。再举一个例子,如果您想为指针 pfoo 指向的其他对象调用它,则调用将如下所示

FOO *pfoo;
...
(pfoo->*fptr)(a, b);

在您的 BAR 类中,调用应如下所示 < code>(this->*fptr)(a,b) 即使 fptr 是局部变量。

Apparently, you misunderstand the meaning of this->* in the call in FOO.

When you use this->* with the member fptr pointer, the this->* part has absolutely nothing to do with fptr being a member of FOO. When you call a member function using a pointer-to-member, you have to use the ->* operator (or .* operator) and you always have to specify the actual object you want to use with that pointer-to-member. This is what the this->* portion of the calling expression does. I.e. the call will always look as

(<pointer-to-object> ->* <pointer-to-member>) (<arguments>)

or as

(<object> .* <pointer-to-member>) (<arguments>)

The left-hand side of the call (<pointer-to-object> or <object> above) cannot be omitted.

In other words, it doesn't matter whether fptr is a member variable, local variable, global variable or any other kind of variable, the call through fptr will always look as

(this->*fptr)(a, b);

assuming that you want to invoke it with *this object. If, for another example, you want to invoke it for some other object pointed by pointer pfoo, the call will look as follows

FOO *pfoo;
...
(pfoo->*fptr)(a, b);

In your BAR class the call should look as (this->*fptr)(a,b) even though fptr is a local variable.

笑忘罢 2024-09-07 02:18:22

当使用成员函数指针时,需要指定它所作用的对象。

也就是说,您需要创建一个指向 BAR 实例的指针(我们称之为 bar)并执行 do:

(bar->*fptr)(a,b)

来调用该函数,或者创建一个 BAR 实例并执行 do:

(bar.*fptr)(a,b)

换句话说:

#include <iostream>

class BAR
{
    int i;
public:
    BAR(): i(0) {};
    int AddOne() { return ++i; };
    int GetI() { return i; };
}

int main()
{
    BAR bar;
    auto fPtr = &BAR::AddOne; // This line is C++0x only (because of auto)
    std::cout << (bar.*fPtr)(); //This will print 1 to the console
    std::cout << std::endl;
    std::cout << bar.GetI(); //This will also print 1 to the console.
}

When you use a member function pointer, you need to specify the object on which it is acting.

I.e. you need to create a pointer to an instance of BAR (let's call it bar) and do:

(bar->*fptr)(a,b)

to call the function, or an instance of BAR and do:

(bar.*fptr)(a,b)

Put another way:

#include <iostream>

class BAR
{
    int i;
public:
    BAR(): i(0) {};
    int AddOne() { return ++i; };
    int GetI() { return i; };
}

int main()
{
    BAR bar;
    auto fPtr = &BAR::AddOne; // This line is C++0x only (because of auto)
    std::cout << (bar.*fPtr)(); //This will print 1 to the console
    std::cout << std::endl;
    std::cout << bar.GetI(); //This will also print 1 to the console.
}
烦人精 2024-09-07 02:18:22

我不认为变量的使用本身是非法的。尝试在没有类实例的情况下调用该方法是非法的。

也就是说,您应该真正调用 (someVar->*fptr)(a,b) ,其中 someVar 的类型为 BAR*

I don't think the usage of the variable itself is illegal. What's illegal is trying to call that method without a class instance.

That is, you should really call (someVar->*fptr)(a,b) where someVar is of type BAR*

最单纯的乌龟 2024-09-07 02:18:22

BAR::call_adder() 有几个问题。其一,你正在混合案例。在 C++ 中,大小写很重要。 BARbar 不同。其次,在修复大小写问题后,您很好地对指针进行了标记和分配,但是当您尝试通过指针调用成员函数时,您需要将 operator ->* 与类对象一起使用。这是 call_adder() 已修复

 void call_adder(int a, int b)
 {  
  int (BAR::*fptr)(int a, int b);
  fptr = &BAR::add_stuff;
  cout<<(this->*fptr)(a,b)<<endl;
 }

BAR::call_adder() had a couple of problems. For one, you were mixing case. In C++, case is signifigant. BAR and bar are not the same. Second, you decalred and assigned the pointer fine, after fixing the case problems, but when you try to call through the pointer to a member function, you need to use operator ->* with a class object. Here's is call_adder() fixed

 void call_adder(int a, int b)
 {  
  int (BAR::*fptr)(int a, int b);
  fptr = &BAR::add_stuff;
  cout<<(this->*fptr)(a,b)<<endl;
 }
一个人的旅程 2024-09-07 02:18:22

当您调用类的成员函数时,编译器会生成代码以在函数运行时设置“this”。当您从未完成的函数指针调用它时。有很多方法可以解决这个问题,但它们不能“保证”工作并且依赖于编译器。只要您小心并知道可能遇到的问题,您就可以做到。

When you invoke a member function of a class the compiler generates code to set 'this' while the function runs. When you call it from a function pointer that isn't done. There are ways to get around it but they aren't 'guaranteed' to work and are compiler dependent. You can do it as long as you're careful and know the possible problems you can run into.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文