이 가이드는 C++ 함수 오버라이딩을 명확한 예제, 모범 사례, 숙련된 C++ 개발자가 실무에서 사용할 단계별 설명으로 풀어냅니다.
함수 오버라이딩이 중요한 이유
객체 지향 프로그래밍에서 상속은 파생 클래스가 기반 클래스의 동작을 확장하거나 수정할 수 있게 합니다. 기반 클래스와 파생 클래스에 같은 멤버 함수가 선언되면 파생 클래스의 구현이 기반 클래스의 것을 "오버라이드(재정의)"합니다. 파생 클래스 객체를 통해 그 함수를 호출하면 오버라이드된 버전이 실행됩니다.
예제 1: 기본 오버라이딩
#include <iostream>
using namespace std;
class Base {
public:
void print() {
cout << "Base Function" << endl;
}
};
class Derived : public Base {
public:
void print() {
cout << "Derived Function" << endl;
}
};
int main() {
Derived d;
d.print();
return 0;
}
출력
Derived Function
Derived 인스턴스에서 print()를 호출하면 기반 버전이 아닌 오버라이드된 함수가 실행됩니다.
Base 객체를 생성해 print()를 호출하면 원래 기반 구현이 실행됩니다.
Base b;
b.print(); // 출력: Base Function
오버라이드된 기반 함수 접근하기
때로는 기반 클래스의 버전을 명시적으로 호출해야 할 때가 있습니다. 두 가지 일반적인 기법은:
범위 지정 연산자 :: 사용.
파생 객체를 가리키는 기반 클래스 포인터 사용(함수가 virtual이 아닐 때).
예제 2: 범위 지정 연산자로 기반 함수 호출
#include <iostream>
using namespace std;
class Base {
public:
void print() {
cout << "Base Function" << endl;
}
};
class Derived : public Base {
public:
void print() {
cout << "Derived Function" << endl;
}
};
int main() {
Derived d1, d2;
d1.print();
d2.Base::print(); // Base::print() 명시적 호출
return 0;
}
출력
Derived Function
Base Function
예제 3: 파생 클래스 내부에서 기반 함수 호출
#include <iostream>
using namespace std;
class Base {
public:
void print() {
cout << "Base Function" << endl;
}
};
class Derived : public Base {
public:
void print() {
cout << "Derived Function" << endl;
Base::print(); // 기반 버전 호출
}
};
int main() {
Derived d;
d.print();
return 0;
}
출력
Derived Function
Base Function
예제 4: 기반 포인터로 기반 함수 접근
#include <iostream>
using namespace std;
class Base {
public:
void print() {
cout << "Base Function" << endl;
}
};
class Derived : public Base {
public:
void print() {
cout << "Derived Function" << endl;
}
};
int main() {
Derived d;
Base* ptr = &d; // 파생 객체를 가리키는 기반 포인터
ptr->print(); // 함수가 virtual이 아니므로 Base::print() 호출
return 0;
}
출력
Base Function
함수가 virtual로 선언되지 않으면 기반 클래스 포인터는 기반 구현을 호출합니다. 진정한 다형적 동작을 원하면 기반 함수를 virtual로 선언하고 파생 클래스에서 오버라이드하세요.
이 예제들은 C++ 함수 오버라이딩의 작동 원리를 보여줍니다. 이 개념들을 마스터하면 다형성을 효과적으로 활용해 더 깔끔하고 유지보수하기 쉬운 코드를 작성할 수 있습니다.