簡體   English   中英

為什么此代碼允許訪問私有變量

[英]Why this code allows accessing private variables

幾天前,我遇到了這種方法(作為C ++課程中編程任務的解決方案之一)。

#include <iostream>

struct C {
    C(int i) { m_i = i; }
private:
    int m_i;
};

template<typename Tag, int C::* M>
struct Rob {
    friend
    int C::* get(Tag) {
        return M;
    }
};

template<typename D>
struct AcessorTag {
    typedef D C::*type;
};

template struct Rob<AcessorTag<int>, &C::m_i>;

int &get_c(C &cls) {
    return cls.*get(AcessorTag<int>());
}

int main()
{
    C c(13);
    std::cout << get_c(c);
    return 0;
}

您能否解釋一下為什么編譯此代碼? 這里發生的幾乎所有事情是:1)我們將指針指向成員作為結構模板的參數傳遞給我們; 2)聲明一個朋友函數,該函數僅將該指針返回給成員。

這是標准的C ++嗎? (我已經在VS 2015上進行了測試)

get函數是struct Rob<>的朋友,但不是struct C 無論如何, struct C似乎沒有朋友,那么為什么它的私有成員可以訪問?

謝謝!

除了缺少get函數的前向聲明外,此代碼還可以正常工作並且符合標准。 由於適用於模板的顯式實例化定義的特殊規則,因此可以使用此代碼:

17.8.2顯式實例化[temp.explicit]

14通常的訪問檢查規則不適用於用於指定顯式實例化的名稱。 [注:特別是,函數聲明符中使用的模板參數和名稱(包括參數類型,返回類型和異常規范)可能是私有類型或對象,通常是無法訪問的,並且模板可能是成員模板或成員函數通常是無法訪問的。 —尾注]

所以寫

template struct Rob<AcessorTag<int>, &C::m_i>;

將繞過常規的訪問檢查,並提供指向否則無法訪問的成員的指針,以get函數體。

這個答案中很好地描述了這種幻想規則的動機。

當然,您的代碼無法使用gnu c ++和clang ++進行編譯; 標識符get不是C的成員。 即使您嘗試實例化Rob ,例如

Rob<AcessorTag<int>, &C::m_i> rob;

您獲得

error: 'int C::m_i' is private.

您可以隨時詢問Microsoft他們的c ++編譯器是否符合任何標准。 如果他們完全回答,請告訴我他們的答案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM