繁体   English   中英

C ++成员函数指针定义

[英]C++ Member Function Pointer Definition

考虑以下代码:

#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)()和这样C (M::*member)

让我们简化为仅考虑以下两者之间的区别:

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

fmember是指向M的成员函数的指针,返回零参数并返回C 如果用&B::func调用它,编译器将推导出M == BC == void 直截了当。

gmember只是指向C类型的M成员的指针。 但是,在我们的例子中, &B::func是一个函数。 所以这里的影响就是放弃指针。 我们再次推导出M == B ,而C变为void() - 现在C是一个函数类型。 这是f一个不太专业的版本,因为它允许更多种类的成员。 g可以匹配带参数的函数,也可以匹配指向成员的指针,或相关地反对cv -qualified member functinos。

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

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推断出一个不带args但不是cv-qualified的成员函数类型,所以类型推导就会失败。 没有CM可以匹配这些类型。

但是, call2扣除很好,因为它更通用。 它可以匹配任何指向成员的指针。 我们最终只得到C = void() const volatile 这就是为什么这样做的原因。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM