이번에는 어찌 보면 좀 황당한(?) 소스코드를 이야기하고자 한다.
참고로 지금 언급하고자 하는 개념은, 어떤 블로그에서는 당당하게 "C++ 클래스의 private 멤버 변수에 접근하고 값을 변경하는 방법!!" 이라고 소개되기도 하였다. (개인적으로 참 난감한 글이었다.)
아래 소스코드를 보자.
#include <iostream> class TempClass { private: const int a; const int b; public: TempClass() : a(100), b(200) {} TempClass(int i, int j) : a(i), b(j) {} int get_a() const { return a; } int get_b() const { return b; } }; int main() { TempClass c; int &aa = *reinterpret_cast<int*>(&c); // int &aa = *(int*)(&c); int &bb = *(reinterpret_cast<int*>(&c)+1); // int &bb = *((int*)(&c)+1); std::cout << "before c.a : " << c.get_a() << " c.b : " << c.get_b() << std::endl; aa = 300; bb = 400; std::cout << "after c.a : " << c.get_a() << " c.b : " << c.get_b() << std::endl; return 0; }
일반적인 class인 TempClass를 정의하였고, private 멤버변수 a, b는 const 이므로 생성자에 의해서만 값이 초기화된다.
그런데 main 함수에서 생성된 클래스 인스턴스의 주소를 받았고 이를 이용하여 reinterpret_cast 를 써서 "억지로" private 멤버에 접근을 하여 참조자를 부여하였다.
(주석처리된 C 스타일의 casting 또한 결국 동일한 의미이다.)
결론은... 역시 정상적으로 컴파일되며 값 또한 변경이 된다.
....................
C, C++ (뿐만 아니라 어느 언어로 프로그래밍을 하든 비슷한 이야기지만) 프로그래밍에서 사용되는 키워드의 의미를 망각하거나 잘못 이해하면 안되겠다.
C, C++ 에서 사용되는 키워드인 const, private 등은 어디까지나 프로그래머를 위한 키워드이지 프로그램을 사용하는 사용자를 위한 키워드가 아니다. 즉, 프로그래머가 위와 같은 키워드를 적절히 사용하여 프로그래밍을 하면, 나중에 그 소스코드를 이용할 때, 혹은 다른 사람이 그 소스코드를 활용할 때 이러한 키워드를 보고 해당 변수, 함수, 객체의 의미를 잘 정립할 수 있으며, 또한 혹시 모를 프로그램상의 오류를 미연에 방지할 수 있다는 데에 의미를 두어야 한다.
결국, 위와 같이 소스코드를 짜 보는 것은 프로그래머의 자유이고, 분명히 한번 궁금해서 실험적으로 해 볼 수 있는 시도임엔 틀림 없다. 무언가를 제한하는 키워드를 사용하는 의의를 역설적으로 음미해 보는 데에는 데에는 분명 유익한 코드이니까.
실전에서 저런 식으로 프로그래밍을 하는 것 만큼 어리석은 짓은 없을 것이다.
저것은 결코 대단한 기술도 아니며, 저걸 "private 변수에 접근할 수 있는 비법" 으로써 안다고 자랑할 만한 거리는 더더욱 아닌 것이다.
마치 뭐랄까, 박물관에 전시된 골동품에 "손대지 마시오!" 라고 적혀진 경고문구를 무시하고 자기 손때를 묻힌 후 만졌다고 자랑하는 거나 다를게 없어보인다는....
적어도 C/C++ 프로그래밍을 할때 const 와 private 등을 제대로 사용할 줄 아는 사람들에게는 저 코드는 정말 stupid한 소스코드이기에.
### Wafting ....... Done !!!
### ...
### ;;
댓글 없음:
댓글 쓰기