首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >C++成员函数指针定义

C++成员函数指针定义
EN

Stack Overflow用户
提问于 2016-02-03 22:20:30
回答 1查看 990关注 0票数 16

考虑下面的代码:

#include <iostream>
#include <functional>

struct B {
    template <class C, class M, class T>
    void call1(C (M::*member)(), T *instance) {
        std::function<void()> fp = std::bind(member, instance);
        fp();
    }

    template <class C, class M, class T>
    void call2(C (M::*member), T *instance) {
        std::function<void()> fp = std::bind(member, instance);
        fp();
    }

    void foo() {
        call1(&B::func, this); // works
        call2(&B::func, this); // works

        call1(&B::func2, this); // Error: no matching member function for call to 'call2'
        call2(&B::func2, this); // works
    }

    void func() {
        std::cout << "func\n";
    }

    void func2() const volatile {
        std::cout << "func2\n";
    }
};

int main() {
    B{}.foo();
}

似乎以后的版本不接受带有额外cv限定符的函数。

像这样指定函数成员指针和像这样指定C (M::*member)有什么区别

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-02-03 22:59:15

让我们简单地考虑一下它们之间的区别:

template <class C, class M> void f(C (M::*member)());
template <class C, class M> void g(C (M::*member));

f中,member是指向M的成员函数的指针,返回零参数并返回C。如果你用&B::func调用它,编译器会推导出M == BC == void。简单明了。

g中,member只是一个指向M类型为C的成员的指针。但是,在我们的例子中,&B::func是一个函数。所以这里的影响就是丢掉指针。我们再次推导出M == B,而C变成了void() -现在C是一个函数类型。这是f的一个非专门化版本,因为它允许更多类型的成员。g可以匹配带参数的函数,或者匹配指向成员的指针,或者相关地匹配cv限定的成员函数。

让我们考虑一个重载函数的例子,以及如何以不同的方式推导它(这是您问题中的原始问题,后来进行了编辑,但仍然很有趣):

struct X {
    void bar() { }
    void bar(int ) { }
};

当我们这样做的时候:

f(&X::bar);

尽管&X::bar是一个重载的名称,但实际上只有一个与C (M::*)()匹配。有M == XC == void的那个。获取intbar重载不可能与模板类型匹配。因此,这是传递重载名称的可接受用法之一。这样可以很好地演绎。

然而,当我们这样做的时候:

g(&X::bar);

现在,有两个完美有效的推论。C可以是void()void(int)。因为两者都是有效的,所以推导是模棱两可的,而且你无法编译--有一个错误并不能让这一点变得特别清楚。

现在回到你的例子:

call1(&B::func2, this); // Error: no matching member function for call to 'call2'
call2(&B::func2, this); // works

&B::func2的类型为void (B::*)() const volatile。由于call1在不带参数且不是cv限定的成员函数类型上进行推导,因此类型推导就会失败。没有使这些类型匹配的CM

但是,call2演绎是很好的,因为它更通用。它可以匹配任何指向成员的指针。我们只是简单地以C = void() const volatile结束。这就是为什么它可以工作的原因。

票数 15
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35179578

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档