簡體   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