在结构体外调用指向函数的指针

3
我有一个结构体,在其中有指向该结构体的相同函数的指针。现在我需要调用该结构体之外的函数指针。以下是代码示例:
#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;
}

2
void (test::*tp)(); - 为什么你把它放在类外面?移除它并修正你的调用语法。 - Mat
2个回答

7
(t.*tp)();试图调用成员函数指针tp,它在全局命名空间中被定义为void (test::*tp)();。请注意,实际上它被初始化为null指针(通过零初始化1),调用它会导致未定义行为,任何可能性都存在。
如果您想在对象t上调用t.tp的数据成员(即tp),您应该将其更改为:
(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) 对于所有静态或线程本地存储期的命名变量,不受常量初始化影响(自C++14以来),在任何其他初始化之前。


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()函数(或任何其他地方),您可以有返回指向基类的指针或引用的函数,它们实际上是子类的实例。这样一来,您就不必担心指针问题了。
缺点是您必须在编译时知道不同的测试(然后甚至不会在使用现场知道,就像我刚解释的那样)。如果您知道,那么我建议使用常见惯用法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接