C++에서는 NULL로 초기화된 클래스 포인터를 통해서도 멤버 함수를 호출할 수 있습니다. 언뜻 이상하게 들리지만, 실제로 컴파일되어 실행되는 코드입니다.
주의 사항
다만 이러한 동작은 정의되지 않은 동작(undefined behaviour)에 해당합니다. 즉, 프로그램이 정상적으로 실행된다는 보장이 전혀 없으며, 실제 결과는 사용하는 컴파일러와 환경에 따라 달라질 수 있습니다. 따라서 실제 프로젝트에서는 이런 방식의 호출을 절대 사용해서는 안 됩니다.
예제 코드
NULL 포인터로 멤버 함수를 호출하는 과정을 보여주는 프로그램은 다음과 같습니다.
#include <iostream>
using namespace std;
class Example {
public :
void func() {
cout << "The function is called through Null class pointer.";
}
};
int main() {
Example *p = NULL;
p->func();
return 0;
}실행 결과
위 프로그램을 실행하면 다음과 같은 출력이 나타납니다.
The function is called through Null class pointer.
코드 설명
위 프로그램의 동작 원리를 단계별로 살펴보겠습니다.
1. 클래스 정의
클래스 Example에는 멤버 함수 func()가 정의되어 있으며, 이 함수는 "The function is called through Null class pointer."라는 문장을 화면에 출력합니다.
class Example {
public :
void func() {
cout << "The function is called through Null class pointer.";
}
};2. NULL 포인터 생성 및 함수 호출
main() 함수 내부에서 Example 타입의 포인터 p를 선언하고 NULL로 초기화합니다. 그런 다음 p-> 연산자를 사용해 func()를 호출합니다.
int main() {
Example *p = NULL;
p->func();
return 0;
}왜 이런 동작이 가능할까?
이 코드가 실행되는 이유는 C++의 멤버 함수 호출 방식 때문입니다. 일반적인 비가상(non-virtual) 멤버 함수는 객체의 주소(즉, this 포인터)를 인자로 넘기는 형태로 컴파일됩니다. 만약 함수 내부에서 멤버 변수나 가상 함수 테이블(vtable)에 접근하지 않고 this 포인터를 사용하지 않는다면, 역참조 오류가 발생하지 않아 겉보기에는 정상적으로 실행되는 것처럼 보입니다.
그러나 이는 어디까지나 우연히 동작하는 것일 뿐입니다. 함수 내부에서 멤버 변수에 접근하거나 가상 함수를 호출하는 순간, NULL 포인터 역참조로 인해 프로그램이 크래시(crash)됩니다. 따라서 이 예제는 C++의 내부 동작 방식을 이해하기 위한 학습용으로만 활용하고, 실제 코드에서는 반드시 유효한 객체를 가리키는 포인터를 사용해야 합니다.