使用成員函數指標的一些注意事項

來源:互聯網
上載者:User

在C++編程中,成員函數指標並不常用,並且由於它實現比較複雜,很容易導致編程錯誤。

基本用法:

class B {
public:
    int f(int a, int b) {
        return (a + b) * m_c;
    }

    int m_c;
};

int main() {

    typedef int (B::*MEM_FUNC)(int, int);  // 定義成員函數指標類型MEM_FUNC
    MEM_FUNC pmf;                          // 定義成員函數指標pmf
    pmf = NULL;  // 指標可以設定為NULL
    pmf = &B::f; // 指標可以指向一個成員函數

    B b1, b2;
    b1.m_c = 10;
    b2.m_c = 20;

    int i1 = (b1.*pmf)(30, 40); // 調用b1.f(30, 40)
    int i2 = (b2.*pmf)(50, 60); // 調用b2.f(50, 60)

    B* p = &b1;
    int i3 = (p->*pmf)(70, 80); // 調用b1.f(70, 80)

    return 0;
}

C++語言最初設計的時候,沒有繼承,沒有虛函數,等等,所以成員函數指標的使用也並不複雜。但是隨著多重繼承、虛擬繼承等特性被引入,成員函數指標開始變得複雜了。

首先是大小的改變。雖然“成員函數指標”是一種指標,但它所佔的空間卻可能比一般指標要大。以VC為例(VC6至VC2010均如此),在單繼承、多繼承、虛擬繼承的情況下,成員函數指標的大小分別為4位元組、8位元組、12位元組。如果不知道一個類是否繼承(此時這個類只有一份向前聲明,而沒有提供實際定義),則它的成員函數指標最多可以佔據16個位元組,大大的超過了一般指標的4位元組。

然後是類型轉換問題。一般情況下,衍生類別的指標轉化為基類的指標不會有任何問題(因為繼承就意味著is a kind of)。但是,衍生類別的成員函數指標卻不可以轉化為基類的成員函數指標。範例程式碼:
int main() {
    typedef void(std::istream::*PMF_B)(int);
    typedef void(std::ifstream::*PMF_D)(int);
    PMF_B b = 0;
    PMF_D d = 0;
    d = b; // 編譯錯誤
    return 0;
}
為什麼編譯錯誤呢?從位元組數來講,因為衍生類別的成員函數指標,它的位元組數可能比基類的成員函數指標更多。如果成功轉換,則會導致位元組數減少,某些有用的資訊可能就丟失了。但更重要的原因是,衍生類別的成員函數指標可以指向衍生類別的函數,而衍生類別的這些函數可能是基類所沒有的。此時,就算成功的完成轉換,在運行之時也肯定導致記憶體錯誤。反過來,如果把基類的成員函數指標轉換為衍生類別的成員函數指標,則是完全可以的。

還有就是關於VC系列編譯器,在一個問題上沒有按照C++標準來處理。標準規定各種成員函數指標之間,可以用reinterpret_cast來完成強制轉換,但VC系列編譯器在實現這一點時有存在問題,可能導致編譯錯誤。解決此問題的辦法是用union hack,具體作法是定義一個union,其中包含了轉換之前和轉換之後的成員指標類型。然後設定/取值即可。

最後,boost提供了一套mem_fn,它是std::mem_fun更加通用的版本(std::mem_fun只支援無參數、單參數版本,boost::mem_fn支援更多參數)。可以把對成員函數的調用轉化為類似普通函數的形式。這一套mem_fn已經被納入到TR1,在VC 2008 SP1和以上版本可以直接使用。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.