2014-06-24 2 views
2

여기에 나와있는 코드에서 아래에 언급 된 두 줄을 이해할 수 없습니다. int*을 사용해야하는 이유는 무엇입니까? 개인 변수에 어떻게 액세스하고 있습니까? 나는이 두 줄로 내가 무엇을하고 있는지 확신하지 못한다. 자세히 설명해주십시오.C++에서 포인터의 타입 캐스팅에 대한 설명

문제있는 라인 :

int *p = (int *) &s; 
*p=10; 

홈페이지 코드 :이 코드는 도움을 클래스에 의해 부과 된 캡슐이 파손 클래스 sample에 회원 a에 액세스하려고

#include <iostream> 

using namespace std; 

class sample { 
private: 
    int a; 
public: 
    void function() { 
    a=5; 
    } 
    void printA() { 
    cout<<"value is "<<a<<endl; 
    } 
}; 

int main() { 
    sample s; 
    s.function(); 
    s.printA(); 

    int *p = (int *) &s; 
    *p=10; 

    s.printA(); 
} 
+0

방금 ​​가상 메서드를 VS에 추가하면 gcc "a"가 변경되지 않습니다. – Arkady

답변

5

(int*)을 사용하면 실제로 정말 좋은 아이디어가 있습니다. int가 아닌 클래스를 int로 사용하고 있습니다. 어느 것이 나쁘다.

비공개 멤버는 액세스 할 수 없으므로 비공개로 설정하면 안됩니다.

int *p = (int *) &s; 
*p=10; 

이 당신은 유형 sample의 객체 s을 가지고, 그것은 데이터 멤버 int a;을 가지고 의미한다. 당신이 쓴 것은 a이 수업의 시작 부분에 있기 때문에 일합니다.

클래스의 레이아웃이 보장되는 경우가 있습니다, 당신은 여기에 대해 읽을 수 있습니다 :

1

포인터 캐스팅 그것은 안전하지 않습니다, 클래스 구성원의 메모리 레이아웃에 따라 다릅니다.

가정은 부재 a 그래서 객체의 주소를 고려하고, 가능한 제 int 부재에 액세스 할 수 있도록한다 int*로 주조하는 sample 객체의 시작 위치에있을 예정이다.

실제로는 a이 첫 번째 위치에 있기 때문에 작동하지만 이것은 패딩/정렬 및 상속 계층 구조로 인해 다른 멤버에 대해서는 작동하지 않으며 작동하지 않습니다. 이 유형의 코드는 위험합니다.

필요한 경우 이러한 종류의 코드를 작성하는 대신 개인 멤버의 접근 자/변경자가 있어야합니다.

+0

"이것은 보장되지 않습니다"- 그렇습니다 (C++ 11 이후), 더 이상 표준 레이아웃이 아니게 클래스를 변경하지 않는 한 그렇습니다. 나는 그러한 변화가 코드를 조용히 깨뜨릴 것이므로 위험하다고 동의한다. 그러나 정말로 필요하다면 그러한 클래스의 레이아웃에 (이식 가능하게) 의존 할 수 있습니다. –

2

이 먼저 떨어져,이 작업을 수행하지하시기 바랍니다.

클래스 sample의 메모리 레이아웃을 활용하고 있습니다. 첫 번째 구성원은 int이며 클래스의 메모리 공간 시작 부분에 있습니다.

a 앞에 다른 int을 추가하면 변경되지 않았 음을 알 수 있습니다.