2017-08-31 58 views
2

我想要的是一些班級成員有時候是private,其他時間是public。這些成員應該可以被某些模塊訪問並且其他人無法訪問。私人/保護/公衆如何影響ABI?

成像這個類:

class Foo { 
public: 
    ... 
private: 
    ... 
protected: 
    ... 
internal: 
    int x; 
}; 

在模塊X的internal定義爲:

#define internal public 

,並在模塊Y它的定義爲:

#define internal private 

所以真正的問題如果這個技巧是標準可接受的,或者它會改變類的簽名(或者它以任何方式。

我知道friendPIMPL是這樣的工作,但friend可以得到非常混亂和PIMPL的性能(的間接和事實,你不能內聯)不是爲我工作的代碼庫可以接受上。

+9

聽起來像是一個ODR違反,因此UB。 UB可能會做你想要的。 – nwp

+2

成員的可見性不會通過編譯器傳遞到生成的代碼中,因此對ABI沒有影響,或者受到ABI的影響。 –

+2

至於'內部宏',它的目的是什麼?它應該解決什麼問題?你有一個用例或需求或導致這種情況的設計?這有[XY問題]的氣味(http://xyproblem.info/)。也許是時候查看你的需求或設計了?這些「模塊」是否會連接在一起形成同一個程序的一部分? –

回答

4

這是一個ODR違規,因此調用未定義的行爲。 (另請參閱basic.def.odr] /6.1「D的每個定義應包含相同的令牌序列」)。

但是,一個常見的實現是public,private,protected對類的佈局沒有影響,所以它可以工作。

你在薄冰上溜冰;沒有什麼能夠阻止編譯器將所有公共成員放在第一位,然後是受保護的成員,然後是私有成員。更關鍵的是,在一般情況下,聲明的順序是必需的,以在存儲器中的順序,以便

struct T {char a; int b; char c}; 

需要具有a,然後b,然後c。這是爲了確保C兼容性。但是,對於具有不同訪問權限的元素的排序沒有要求(請參閱[class.mem] /9.2 p13:「分配了具有相同訪問控制(第11章)的(非聯合)類的非靜態數據成員,以便後構件的一類對象中具有較高的地址。與不同的訪問控制非靜態數據成員的分配的順序是不確定的(第11章)」。因此,給定的

struct T {char a; int b; private: char c}; 

編譯器可以重新排序部件,並把cab之間的差距

最後注意到EJP和其他誰認爲這些聲明不是定義:我給n兩個的定義T以上;一個聲明看起來像struct T;

編輯:感謝Fanael的引用來自標準。

+2

這是正確的,另請參見[basic.def.odr] /6.1「D的每個定義應由相同的令牌序列組成」明顯違反如果內部是在一個TU中是「公共」而在另一個TU中是「private」的話。 – Fanael

+0

我認爲C++明確禁止編譯器重新排序成員。 – nwp

+1

@nwp:從標準「具有相同訪問控制的(非聯合)類的非靜態數據成員(第11章)被分配爲 ,以便後面的成員在類對象內具有更高的地址。靜態數據 具有不同訪問控制的成員未指定(第11章)「 –

0

C++最初似乎認爲私人成員可以放置在除公共成員旁邊的地方,也許這樣他們可以成爲硬件中的受保護區域,所以可以想象公共和私人部分可以相對於彼此。

有可能不通過中藥口吃GOTW 76重新界定公共/私人使用技巧,並完成了一個全功能的系統,這裏該數據litb safer private member access

給出一個類,如下所示,以測試你的代碼....

struct A { 
    A(int a):a(a) { } 
private: 
    int a; 
}; 

需要一個類強盜......

template<typename Tag, typename Tag::type M> 
struct Robber { 
    friend typename Tag::type get(Tag) { 
    return M; 
    } 
}; 

實用程序類,允許多個搶斷....

template<typename Tag, typename Member> 
struct TagBase { 
    typedef Member type; 
    friend type get(Tag); 
}; 

聲明一個盜竊意圖成爲

struct A_f : TagBase<A_f, int A::*> { }; 
template struct Robber<A_f, &A::a>; 

然後竊取數據....

int main() { 
    A a(42); 
    std::cout << "proof: " << a.*get(A_f()) << std::endl; 
}