C++ 有没有一种方法可以在没有。*或->;*的情况下调用成员函数操作人员
下面通过指向成员函数的指针调用C++ 有没有一种方法可以在没有。*或->;*的情况下调用成员函数操作人员,c++,boost,cdecl,C++,Boost,Cdecl,下面通过指向成员函数的指针调用D::foo函数的方法将生成错误:必须使用*或->*调用指向“f(…)”中成员函数的指针。 .. 当然,这不是我们调用成员函数指针的方式 正确的调用方式是(d.*f)(5)或(p->*f)(5) 我的问题是,‘有没有一种方法可以在左侧没有类对象的情况下调用类的成员函数?我想知道是否可以将类对象(this)作为常规参数传递 在我看来,在一天结束时(在汇编/二进制级别),一个类的所有成员函数都是正常函数,应该在n+1个参数上操作,其中(+1代表this) 如果我们在下面
D::foo
函数的方法将生成错误:必须使用*
或->*
调用指向“f(…)”中成员函数的指针。
.. 当然,这不是我们调用成员函数指针的方式
正确的调用方式是(d.*f)(5)代码>或(p->*f)(5)代码>
我的问题是,‘有没有一种方法可以在左侧没有类对象的情况下调用类的成员函数?我想知道是否可以将类对象(this
)作为常规参数传递
在我看来,在一天结束时(在汇编/二进制级别),一个类的所有成员函数都是正常函数,应该在n+1个参数上操作,其中(+1代表this
)
如果我们在下面讨论D::foo
函数,那么在程序集/二进制级别,它应该在两个参数上操作:
类对象本身(指向名为this
的D类对象的指针)
和int
那么,有没有一种方法(或hack)来调用D::foo
,将class对象作为函数参数传递给它,而不是使用。或->或。*或->*
类对象上的运算符
示例代码:
#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;
}
编辑:
“请注意,我不是在寻找这个程序的一个有效版本,我知道如何使它工作”我不太确定您的要求。通过指向成员的指针调用函数没有“人为限制”;您只需使用正确的语法:
(d.*f)(5); // for objects or references
(p->*f)(5); // for pointers
bind
没有任何“魔力”;在它的实现中,它确实做到了这一点
最后,它是一个接受两个参数的函数
不,它是一个成员函数,接受一个参数,并在对象上调用。虽然在概念上类似于接受两个参数的函数,但有一个很大的区别:成员函数可以是虚拟的,涉及运行时调度机制
但必须有一种方法来避免这种人为的限制
由c强加++
你所说的“人为限制”是什么意思?这只是语言定义的语法。怎么了?bind()
的“魔力”将在内部使用->*
操作符来调用函数。您真的想在不使用
或->
的情况下调用成员函数吗?真的吗,真的吗?好吧,好吧
邪恶。h:
#ifdef __cplusplus
extern "C" {
#endif
struct MyStruct
{
#ifdef __cplusplus
MyStruct();
void method(int);
#endif
};
#ifdef __cplusplus
}
#endif
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; }
这恰好适用于我在Linux上的gcc和g++组合,但不用说它依赖于平台ABI,并且在调用下划线大写字母形式的函数时违反了C89标准。它几乎肯定不会与虚拟函数一起工作,我也不想尝试。这可能也是我写过的最邪恶的东西。但还是
编辑:引用OP:
在我看来,在一天结束时(在汇编/二进制级别),一个类的所有成员函数都是正常函数,应该在n+1个参数上操作,其中(+1代表this
)
虽然自CFront以来的每个编译器都是这样做的,但这只是一个实现细节。C++标准是在Prime< Stime>不中指定成员函数应该如何实现,而只是它们应该如何执行。
因为这是一个实现细节,不同的平台以不同的方式实现。这不仅仅是名称上的混乱。例如,Linux上使用的调用约定指定将this
作为第一个参数传递;其他实现(Borland,IIRC?)将这个作为最后一个参数
因此,如果您想将成员函数视为具有额外this
的普通函数,那么您必须将自己限制为特定的ABI。这篇文章提供了一个你如何做到这一点的例子(或者更确切地说,一个你为什么真的不应该这么做的例子!)
那么,有没有一种方法(或黑客)调用D::foo,并将类对象作为函数参数传递给它,而不是使用。类对象上的or->or.*或->*运算符
一个特定于平台的恶心的肮脏黑客
有没有一种方法可以在左侧没有类对象的情况下调用类的成员函数
那么,有没有一种方法(或hack)可以调用D::foo
,将class对象作为函数参数传递给它,而不是在class对象上使用
或->
或*
运算符
简而言之,不可以。如果不在调用的左侧指定对象,就不能调用非静态
类成员函数。如果未指定类(对于静态函数)或对象(对于非静态函数),则编译器无法知道要调用哪个函数。它位于当前范围之外,因为它位于类或对象内部。有几种方法可以“破解”代码,这样您就可以将其编写成示例中的main()
。其他一些答案给出了这类黑客的例子
------------使用静态函数-----------------
类内的函数可以在类外调用,而无需指定类对象。方法是为函数指针创建一个签名与类函数匹配的typedef
,然后创建这样一个指针并为其分配类函数的地址。然后可以调用该函数,而无需在左侧指定类或对象
函数必须是静态的
。ISO C++不允许使用绑定成员函数的地址来形成指向该函数的指针,即不能从类对象创建指向非代码>静态< /COD>成员函数的指针。您可能会找到一些非ISO标准兼容的编译器,但我没有任何指导
参数this
为非static
cla
#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; }
#include "evil.h"
int main()
{
struct MyStruct my_struct;
_ZN8MyStructC1Ev(&my_struct); /* MyStruct::MyStruct() */
_ZN8MyStruct6methodEi(&my_struct, 3); /* MyStruct::method(int) */
return 0;
}
fastdelegate::FastDelegate0<> functionObject;
SomeClass someInstance;
//fill in object and function information in function object
functionObject.bind(&someInstance,&SomeClass::someFunction);
//call function via object. Equivalent to: someInstance->someFunction();
functionObject();
#include <iostream>
using namespace std;
class D {
public:
void foo ( int a ) {
cout << "D" << endl;
}
int data;
};
typedef void ( D::* Func)(int);
int main ( void )
{
D d;
D *pThis = &d;
Func f = &D::foo;
/* invoke function pointer via a "class" pointer */
(pThis->*f)(5);
/* invoke function pointer via a "class" object */
(d.*f)(5);
return 1;
}
~/prj/stackoverflow
# g++ funcptr.cpp
~/prj/stackoverflow
# ./a.out
D
D
void foo(int a) {}
static void foo(D *pthis, int a) {}
int main(void)
{
D d;
int a = 0;
D::foo(&d, a); /* call foo, w/o using . or -> and providing your own this pointer */
return 0;
}
#include <iostream>
using namespace std;
class D {
public:
void foo ( int a ) {
cout << "D" << endl;
}
int data;
};
template<class Object, class Param, class Function>
class FunctionPointerHelper
{
private:
Function m_function;
public:
FunctionPointerHelper(Function function) :
m_function(function)
{
}
void operator=(Function function)
{
m_function = function;
}
void operator()(Object& object, Param param) const
{
(object.*m_function)(param);
}
};
#define TYPEDEF_NICE_FUNCTION(RESULT, CLASS, NEW_TYPENAME, PARAM) \
typedef RESULT ( CLASS::* NEW_TYPENAME_INTERMEDIATE)(PARAM) ; \
typedef FunctionPointerHelper<CLASS, PARAM, NEW_TYPENAME_INTERMEDIATE> NEW_TYPENAME;
TYPEDEF_NICE_FUNCTION(void, D, Func, int)
int main ( void )
{
D d;
Func f = &D::foo;
f(d, 5);
return 1;
}
#include <iostream>
using namespace std;
class D {
public:
void foo ( int a ) {
cout << "D" << endl;
}
static void foo(D& d, int a)
{
d.foo(a);
}
int data;
};
void foo(D& d, int a)
{
d.foo(a);
}
int main ( void )
{
D d;
D::foo(d, 5);
foo(d, 5);
return 0;
}
int main ( void )
{
D d;
auto f = std::bind( &D::foo, _1, _2 );
f(&d, 5);
}
#include <iostream>
template<typename T, typename Ret, typename... Args>
Ret call_member(Ret (T::*mem)(Args...), T* obj, Args... args)
{
return (obj->*mem)(args...);
}
struct S {
void foo(int i) { std::cout << "Foo: " << i << '\n'; }
};
int main()
{
S s;
call_member(&S::foo, &s, 5);
return 0;
}