在以下程序中,如何将bar转换为foo?
#include <iostream>
namespace NA {
class A {
public:
int (*foo)(int);
};
}
namespace NB {
class B : public NA::A {
public:
int bar(int i) {
std::cout << i << std::endl;
return i*2;
}
B() {
this->foo = bar; // how to type cast this fn pointer?
}
};
}
int main() {
NA::A *a = new NB::B();
std::cout << a->foo(2) << std::endl;
}
我尝试了如下的类型转换,但是在运行程序时出现了严重错误:
B() {
typedef int (*TypeFoo)(int);
this->foo = reinterpret_cast<TypeFoo> (&bar);
}
这是我跑步时的结果:
$ ./a.out
31947824
63895648
我期望2和4。如何对上面的成员函数指针进行类型转换?
更新: 看到表示上述问题没有解决方案的响应后,我将使用我要解决的特定问题进一步更新此问题。
请参阅https://boringssl.googlesource.com/boringssl/+/HEAD/include/openssl/ssl.h#1173-我正在尝试使结构 ssl_private_key_method_st 的不同实例在不同的私钥上运行。我试图从 ssl_private_key_method_st 继承另一个结构,并让 sign / decrypt / complete 方法对继承的结构的实例变量进行操作。
我知道使用 SSL_ [sg] et_ex_data 将数据间接传递给这些函数,但我一直在寻找一种更简单/直接的方式,将实例数据传递给这些函数。< / p>
答案 0 :(得分:2)
您正在遇到未定义的行为。
TypeFoo
和bar
是不同类型的函数指针(分别为int (*)(int)
和int (NB::B::*)(int)
)。
虽然可以相互转换,但使用结果调用函数将导致不确定的行为。
8.2.10重新解释演员[expr.reinterpret.cast]
...
6。可以将函数指针显式转换为其他类型的函数指针。 [注意:通过指向与函数定义中使用的类型不同的函数类型(11.3.5)的指针调用函数的效果是不确定的。 —结束语]除了将“ pointer to T1”类型的prvalue转换为“ pointer to T2”类型(其中T1
和T2
是函数类型)并返回其原始类型以外,都会产生原始指针值,这种指针转换的结果是不确定的。 [注意:另请参见7.11 指针转换的详细信息。 —尾注]
答案 1 :(得分:2)
简短的回答:您不会。
非静态成员函数指针很奇怪。调用其中一个涉及一个秘密的this
参数,它们可能是也可能不是virtual
。这使得它们无法与普通的函数指针混合使用。
您应该考虑使用std::function<int(int)>
而不是int (*)(int)
。这将允许您存储类似以下lambda的内容:
B(){
std::function<int(int)> myfn = [this](int x){
return bar(x);
};
}
此lambda通过引用捕获当前对象,并且此引用存储在std::function
对象本身内部。但是,您也可以直接或通过lambda或bind表达式将任何其他函数分配给std::function
。
另一方面,如果您的bar
方法实际上并不依赖实例,则只需使其为static
。这将使其与常规函数指针混合使用,因为它不再需要秘密的this
,而不再是virtual
。
static int bar(int i) {
std::cout << i << std::endl;
return i*2;
}
这样写,&B::bar
可以分配给常规的int (*)(int)
函数指针。
答案 2 :(得分:1)
您的TypeFoo
定义了一个指向常规函数的指针,而bar
是一种方法。每个非静态方法都有一个隐式的第一个参数this
。
因此,您应该确定自己需要什么:常规函数(在这种情况下,将bar
设为静态)或方法,在这种情况下,您应该像这样键入:
typedef int (B::*TypeFoo)(int);
reinterpret_cast
是容易出错的做法。如果没有它就无法进行转换-您的代码很可能不正确。
答案 3 :(得分:0)
调用成员函数指针确实很痛苦。我建议您按照以下方式进行操作,简化许多上下文处理:
#include <iostream>
namespace NA {
class A {
public:
int (A::*foo)(int);
};
}
namespace NB {
class B : public NA::A {
public:
int bar(int i) {
std::cout << i << std::endl;
return i*2;
}
int callFoo(int x) {
return (this->*foo)(x);
}
B() {
this->foo = (int(A::*)(int)) (&B::bar);
}
};
}
int main() {
NA::A *a = new NB::B();
std::cout << ((NB::B*)a)->callFoo(2) << std::endl;
}
答案 4 :(得分:-1)
指针到成员函数不能像常规指针那样工作。 它保存了函数在类布局中的“相对地址”。因此请使用静态声明函数。 喜欢:
static int bar(int i)
{
// code here
}