有没有办法在没有.*或 - >*运算符的情况下调用成员函数

Vis*_*war 10 c++ boost cdecl

下面D::foo通过指向成员函数调用函数的方法将产生错误:必须使用.*->*调用'f(...)'中的指针到成员函数... 当然这不是我们如何调用指针到 -成员职能.

正确的呼叫方式是(d.*f)(5);OR(p->*f)(5);

我的问题是,'有没有办法在没有左侧的类对象的情况下调用类的成员函数?我想知道我们是否可以将class object(this)作为常规参数传递?

在我看来,在一天结束时(在汇编/二进制级别),类的所有成员函数都是普通函数,它们应该在n + 1个参数上运行,其中(+ 1表示this)

如果我们谈论D::foo下面的函数,在汇编/二进制级别它应该运行两个参数:

  1. 类对象本身(指向D类对象的指针this)
  2. int.

那么,有没有一种方法(或hack)调用D::foo传递给它的类对象作为函数参数而不是. or -> or .* or ->*在类对象上使用运算符?

示例代码:

#include <iostream>
using namespace std;

class D {
    public:
        void foo ( int a ) {
            cout << "D" << endl;
        }

        int data;
};


//typedef void  __cdecl ( D::*  Func)(int);
typedef void ( D::*  Func)(int);

int main ( void ) 
{
    D d;

    Func f = &D::foo;
    f(&d, 5);

    return 1;
 }
Run Code Online (Sandbox Code Playgroud)

一种方法是使用boost bind即

(boost:: bind (&D::foo, &d, 5)) ();
Run Code Online (Sandbox Code Playgroud)

编辑:"请注意我不是在寻找一个有效的程序版本,我知道如何让它工作"

Tri*_*dle 19

你真的想在不使用.或调用成员函数的情况下->?真的,真的吗?哦,那好吧...

Evil.h:

#ifdef __cplusplus
extern "C" {
#endif

struct MyStruct
{
#ifdef __cplusplus
    MyStruct();

    void method(int);
#endif
};

#ifdef __cplusplus
}
#endif
Run Code Online (Sandbox Code Playgroud)

Evil.cc:

#include <iostream>

#include "evil.h"

MyStruct::MyStruct() { std::cout << "This is MyStruct's constructor" << std::endl; }

void MyStruct::method(int i) { std::cout << "You passed " << i << std::endl; }
Run Code Online (Sandbox Code Playgroud)

Evil.c:

#include "evil.h"

int main()
{
    struct MyStruct my_struct;
    _ZN8MyStructC1Ev(&my_struct); /* MyStruct::MyStruct() */

    _ZN8MyStruct6methodEi(&my_struct, 3); /* MyStruct::method(int) */

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这恰好适用于我在Linux上组合gcc和g ++,但不用说它依赖于平台ABI,并且在调用表单下划线 - 大写字母的函数时违反了C89标准.它几乎肯定不适用于虚函数,我不倾向于尝试.它也可能是我写过的最邪恶的东西.但还是......


编辑:引用OP:

在我看来,在一天结束时(在汇编/二进制级别),类的所有成员函数都是普通函数,它们应该在n + 1个参数上运行,其中(+ 1表示this)

虽然自从CFront以来每个编译器都是这样做的,但这只是一个实现细节.C++标准很难不指定成员函数应该如何实现,以及它们应该如何表现.

因为它是一个实现细节,不同的平台以不同的方式进行.这不仅仅是名称错误.例如,Linux上使用的调用约定指定将this其作为第一个参数传递; 其他实现(Borland,IIRC?)this作为最后一个参数传递.

因此,如果您希望将成员函数视为具有额外的普通函数this,则必须将自己限制为特定的ABI.这篇文章提供了一个如何做到这一点的例子(或者更确切地说,为什么你真的不应该这样做的一个例子!)

所以,有没有办法(或黑客)调用D :: foo与类对象传递给它作为函数参数而不是使用.或 - >或.*或 - >*类对象上的运算符?

特定于平台,令人作呕的肮脏黑客......

  • 用于告诉"this"作为不可见的第一个参数的大+1是一个实现细节,并没有由标准指定.另外还提​​供有效的解决方案 (2认同)
  • @TristanBrindle:我已经将我的赏金授予了这个答案,以理解这个问题并提供足够的内容(主要用于编辑部分:))。我还要感谢您为撰写此答案付出的时间和精力。 (2认同)

Mik*_*our 14

我不太确定你在问什么.通过指向成员的指针调用函数没有"人为限制"; 你只需要使用正确的语法:

(d.*f)(5);  // for objects or references
(p->*f)(5); // for pointers
Run Code Online (Sandbox Code Playgroud)

bind不做任何"魔术"; 在其实现的某个地方,它就是这样做的.

在一天结束时,它是一个需要两个参数的函数

不,它是一个成员函数,它接受一个参数,并在一个对象上调用.虽然在概念上类似于带有两个参数的函数,但有一个很大的区别:成员函数可以是虚拟的,涉及运行时调度机制.