我有一个结构,在其中有一个指向相同结构起作用的指针。现在,我需要调用一个指针以在结构外部起作用。我举一个下面的代码示例:
#include <iostream>
struct test {
void (test::*tp)(); // I need to call this pointer-to-function
void t() {
std::cout << "test\n";
}
void init() {
tp = &test::t;
}
void print() {
(this->*tp)();
}
};
void (test::*tp)();
int main() {
test t;
t.init();
t.print();
(t.*tp)(); // segfault, I need to call it
return 0;
}
答案 0 :(得分:7)
(t.*tp)();
试图调用成员函数指针tp
,该成员函数指针在全局名称空间中定义为void (test::*tp)();
,请注意实际上它已初始化为空指针(通过zero initialization 1 ),调用它会导致UB,一切皆有可能。
如果要调用对象tp
上t
(即t.tp
)的数据成员t
,则应将其更改为
(t.*(t.tp))();
^
|
---- object on which the member function pointed by tp is called
如果您确实要调用全局tp
,则应适当地对其进行初始化,例如
void (test::*tp)() = &test::t;
那么您可以
(t.*tp)(); // invoke global tp on the object t
1 关于零初始化
在以下情况下执行零初始化:
1)对于任何具有静态或线程本地存储持续时间
that is not subject to constant initialization (since C++14)
的命名变量,在进行任何其他初始化之前。
答案 1 :(得分:0)
@songyuanyao的答案是有效的。但是,您确定要以这种方式使用结构吗?为什么不只使用继承和虚拟方法呢? :
class base_test {
public:
virtual void t() { std::cout << "test\n"; }
void print() { t(); }
};
然后可以将其子类化:
class my_test : base_test {
public:
virtual void t() { std::cout << "my test\n"; }
};
在main()
函数中(或任何位置),您可以具有返回基类的指针或引用的函数,而基类实际上是子类的实例。这样,您不必担心指针。
不利之处在于,您必须在编译时就了解不同的测试(如我刚才所解释的那样,甚至在使用现场也是如此)。如果您愿意,我会采用常见的习惯用法。