2017-02-28 126 views
1

訪問和更改值的私有成員:更改私有類成員的類

#include <stdio.h> 

class hack_Me 
{ 
private: 
    size_t age; 
public: 
    size_t getAge() const 
    { 
     return this->age; 
    } 

    explicit hack_Me(size_t age):age(age) { } 

}; 

void change_age(hack_Me* h) 
{ 
    *((int*)h) = 100; 
} 

int main(int argc, char* argv[]) 
{ 
    hack_Me h(12); 
    printf("%d \n", h.getAge()); 
    change_age(&h); 
    printf("%d \n", h.getAge()); 

    getchar(); 
    return 0; 
} 

它打印出它適用於MSVC 14

100後12

這種行爲是不確定的和/或編譯器依賴?

更新:StackOverflow是否爲您提供downvotes積分?

+1

c沒有課程,請刪除c標記 –

+1

類似這樣的問題正在等待錯誤,因爲演員完全跳過了任何編譯器檢查。爲什麼不''void change_age(hack_Me * h){* h = hack_Me(100); }'? – zett42

回答

4

這種行爲是未定義的和/或編譯器的依賴?不管變量是否是一個類的內部

使用int*訪問size_t類型的變量是壞的,或者是本身。

如果使用

*(reinterpret_cast<size_t*>(h)) = 100; 

它不是不確定的行爲,它不依賴於編譯器。我懷疑,它不會是,如果你使用任何不同:

*((size_t*)h) = 100; 

你的類是否滿足標準佈局struct的要求。

從C++ 11標準:

9類

...

7所述的標準佈局類是一類:

- 具有沒有類型的非標準佈局類(或這種類型的數組)的非靜態數據成員或參考,

- 沒有虛函數(10.3),並且沒有虛基類(10.1),

- 具有用於所有非靜態數據成員相同的訪問控制(第11),

- 不具有非標準佈局基類,

- 在大多數派生類中最多有一個非靜態數據成員,最多隻有一個具有非靜態數據成員的基類,或者沒有包含非靜態數據成員的基類,以及

- 沒有與第一個非靜態數據成員相同類型的基類。

8.一種標準佈局結構類鍵struct類密鑰class定義的標準佈局類。

對於標準佈局struct s時,指針到一個對象可以被混疊到指針到第一構件變量。

從C++ 11標準:

9.2類成員

...

20指向一個標準佈局結構對象,適宜地使用reinterpret_cast轉換,指向其初始成員(或者如果該成員是位域,則指向其所在的單位),反之亦然。 [注意: 因此,在標準佈局結構對象中可能存在未命名的填充,但不是在其開頭,因爲需要實現適當的對齊。 - 注完]

+0

謝謝您的全面解答。 –

+0

@ Person.Junkie,不客氣。 –

+0

從'size_t'投射到'int'使事情複雜化 – sp2danny

1

的hack_Me裏面你有size_t age;這可能比INT小(例如,在8位架構則可能是的sizeof(爲size_t)== 1和sizeof(int)的== 2 )。如果編譯器在hack_Me的末尾沒有生成填充,則可能發生整個hack_Me小於int的情況,因此*((int*)h) = 100;可能會覆蓋比hack_Me的第一個成員更多的內存。將黑客更改爲*((size_t*)h) = 100;,這可能是確定的(請參閱其他答案)。