2026년 상식닷컴 선정 식당 & 카페 리스트
최근에 오픈한 호텔을 찾는다면 살펴보세요

C++에서 가상 함수란 무엇인가요?

_____
Q1: 가상 함수(Virtual Function)란 무엇인가요?
A1: 가상 함수는 기본 클래스에서 선언되고 파생 클래스에서 재정의할 수 있는 멤버 함수입니다. 런타임에 호출할 함수가 결정되며, 이를 통해 다형성(polymorphism)을 구현할 수 있습니다.

Q2: 가상 함수를 어떻게 선언하나요?
A2: 함수 선언 앞에 `virtual` 키워드를 붙여 선언합니다. 예:
```cpp
class Base {
public:
virtual void func();
};
```

Q3: 가상 함수의 주요 특징은 무엇인가요?
A3:
- 동적 바인딩(런타임 바인딩)을 사용해 호출 함수가 결정됩니다.
- 포인터나 참조를 통해 객체를 접근할 때 파생 클래스의 함수가 호출됩니다.
- 기본 클래스에 `virtual`로 선언된 함수는 파생 클래스에서 재정의(오버라이드)할 수 있습니다.

Q4: 가상 함수를 사용하면 어떤 이점이 있나요?
A4: 다형성을 지원하여, 기본 클래스 타입의 포인터나 참조를 통해 파생 클래스의 적절한 함수가 호출되도록 할 수 있습니다. 모듈화, 유지보수성이 향상됩니다.

Q5: 가상 함수 테이블(Virtual Table, vtable)은 무엇인가요?
A5: 각 클래스는 가상 함수들을 관리하기 위해 가상 함수 테이블을 가집니다. 객체는 이 테이블을 가리키는 포인터(vptr)를 포함하며, 이를 통해 런타임에 올바른 함수 주소로 호출을 연결합니다.

Q6: 가상 함수의 호출은 어떻게 처리되나요?
A6: 컴파일 시점이 아닌 실행 시점에 가상 함수 테이블을 참조하여 실제 호출할 함수 주소를 결정합니다. 이것을 동적 바인딩이라고 합니다.

Q7: 기본 클래스가 아닌 파생 클래스에서 함수에 `virtual`을 다시 명시해야 하나요?
A7: 아닙니다. 기본 클래스에서 `virtual`로 선언된 함수는 파생 클래스에서도 자동으로 가상 함수입니다. 다만 가독성을 위해 다시 명시할 수 있습니다.

Q8: 가상 함수가 아닌 함수는 어떻게 호출되나요?
A8: 가상 함수가 아닌 함수는 정적 바인딩되어 컴파일 타임에 함수가 결정됩니다. 따라서 기본 클래스 포인터로는 파생 클래스 함수 호출이 불가능합니다.
Q9: 순수 가상 함수(Pure Virtual Function)란 무엇인가요?
A9: 함수 선언 뒤에 `= 0`을 붙여 선언한 가상 함수로, 해당 함수는 구현하지 않고 파생 클래스에서 반드시 구현하도록 강제합니다. 이를 포함한 클래스는 추상 클래스가 됩니다.

예:
```cpp
class Base {
public:
virtual void func() = 0; // 순수 가상 함수
};
```

Q10: 가상 함수의 오버라이딩과 숨김(Hiding)은 어떻게 다른가요?
A10: 오버라이딩은 기본 클래스의 가상 함수를 파생 클래스가 같은 시그니처로 다시 구현하는 것이고, 숨김은 시그니처가 다르거나 가상 함수가 아닌 경우 파생 클래스에서 새로운 함수가 같은 이름으로 정의되어 기본 클래스 함수가 보이지 않는 현상입니다.

Q11: 가상 함수의 성능 비용이 있나요?
A11: 가상 함수 호출은 일반 함수 호출보다 약간 더 많은 오버헤드가 있습니다(가상 함수 테이블 조회 및 포인터 역참조). 하지만 대부분의 경우 큰 영향을 미치지 않습니다.

Q12: 소멸자(destructor)는 가상 함수로 선언해야 하나요?
A12: 네, 기본 클래스를 상속할 경우 소멸자를 가상 함수로 선언하는 것이 중요합니다. 그래야 파생 클래스 객체가 기본 클래스 포인터로 삭제될 때 올바르게 소멸자가 호출됩니다.

예:
```cpp
class Base {
public:
virtual ~Base() {}
};
```

Q13: 가상 함수는 다중 상속에서 어떻게 작동하나요?
A13: 다중 상속 시 각 기본 클래스마다 가상 함수 테이블이 생성되고, 객체는 각 테이블을 가리키는 포인터를 가지게 됩니다. 호출 시점에 올바른 테이블을 참조해 함수가 호출됩니다.

---

요약: C++에서 가상 함수는 다형성을 구현하는 핵심 메커니즘으로, 런타임에 호출할 함수를 결정하여 유연하고 확장 가능한 클래스 설계를 가능하게 합니다.
C++에서 가상 함수(Virtual Function)는 객체 지향 프로그래밍의 중요한 개념 중 하나로, 다형성을 구현하는 데 핵심적인 역할을 합니다. 가상 함수는 주로 상속 관계에 있는 클래스에서 사용되며, 런타임에 어떤 함수가 호출될지를 결정하는 메커니즘을 제공합니다. 이를 통해 프로그램의 유연성과 확장성을 높일 수 있습니다. 1. 가상 함수의 정의 가상 함수는 기본 클래스에서 선언되며, 파생 클래스에서 재정의(override)할 수 있는 멤버 함수입니다. 기본 클래스에서 가상 함수로 선언된 함수는 파생 클래스에서 동일한 이름과 매개변수를 가진 함수로 재정의할 수 있습니다. 이때, 기본 클래스의 포인터나 참조를 통해 파생 클래스의 객체를 참조할 경우, 실제 객체의 타입에 따라 적절한 함수가 호출됩니다. 2. 가상 함수의 선언 가상 함수는 기본 클래스에서 `virtual` 키워드를 사용하여 선언합니다. 예를 들어: ```cpp class Base { public: virtual void show() { std::cout << "Base class show function called." << std::endl; } }; class Derived : public Base { public: void show() override { // override 키워드는 선택적이지만 권장됨 std::cout << "Derived class show function called." << std::endl; } }; ``` 위의 예제에서 `Base` 클래스의 `show` 함수는 가상 함수로 선언되었고, `Derived` 클래스에서 이를 재정의했습니다. 3. 다형성(Polymorphism) 가상 함수의 가장 큰 장점은 다형성을 제공한다는 것입니다. 다형성은 동일한 인터페이스를 통해 서로 다른 객체를 다룰 수 있게 해줍니다. 예를 들어, 다음과 같이 사용할 수 있습니다: ```cpp void display(Base* b) { b->show(); // 런타임에 어떤 show()가 호출될지 결정됨 } int main() { Base b; Derived d; display(&b); // Base class show function called. display(&d); // Derived class show function called. return 0; } ``` 위의 코드에서 `display` 함수는 `Base` 클래스의 포인터를 매개변수로 받습니다. 이 포인터가 `Base` 객체를 가리킬 때와 `Derived` 객체를 가리킬 때 각각 다른 `show` 함수가 호출됩니다. 4. 가상 함수 테이블(Virtual Table) 가상 함수는 내부적으로 가상 함수 테이블(vtable)이라는 구조를 사용하여 구현됩니다. 각 클래스는 자신만의 vtable을 가지며, 이 테이블은 해당 클래스의 가상 함수에 대한 포인터를 저장합니다. 객체가 생성될 때, 해당 객체는 자신의 클래스의 vtable을 가리키는 포인터를 가지고 있습니다. 이를 통해 런타임에 적절한 함수가 호출될 수 있습니다. 5. 순수 가상 함수와 추상 클래스 가상 함수는 순수 가상 함수로 선언될 수도 있습니다. 순수 가상 함수는 기본 클래스에서 구현이 없고, 파생 클래스에서 반드시 재정의해야 하는 함수입니다. 순수 가상 함수는 다음과 같이 선언합니다: ```cpp class AbstractBase { public: virtual void show() = 0; // 순수 가상 함수 }; ``` 이렇게 선언된 클래스는 추상 클래스가 되며, 직접 인스턴스를 생성할 수 없습니다. 반드시 파생 클래스에서 이 함수를 구현해야 합니다. 6. 가상 소멸자 가상 함수는 소멸자에도 적용할 수 있습니다. 기본 클래스의 소멸자를 가상으로 선언하면, 파생 클래스의 객체가 삭제될 때 올바른 소멸자가 호출됩니다. 이는 메모리 누수를 방지하는 데 중요합니다. ```cpp class Base { public: virtual ~Base() { std::cout << "Base destructor called." << std::endl; } }; class Derived : public Base { public: ~Derived() { std::cout << "Derived destructor called." << std::endl; } }; ``` 7. 성능 고려사항 가상 함수는 다형성을 제공하지만, 성능 측면에서 약간의 오버헤드가 발생합니다. 이는 함수 호출 시 vtable을 참조해야 하기 때문입니다. 따라서 성능이 중요한 경우, 가상 함수를 사용하기 전에 신중하게 고려해야 합니다. 결론 C++에서 가상 함수는 객체 지향 프로그래밍의 핵심 요소로, 다형성을 통해 코드의 유연성과 재사용성을 높이는 데 기여합니다. 가상 함수의 사용은 상속과 함께 이루어지며, 이를 통해 다양한 객체를 동일한 인터페이스로 다룰 수 있습니다. 가상 함수와 관련된 개념들을 잘 이해하고 활용하면, 더 나은 객체 지향 프로그래밍을 할 수 있습니다.
작성자: 이주영 [비회원] | 작성일자: 1년 전 2024-09-20 17:11:27
조회수: 175 | 댓글: 0 | 좋아요: 0 | 싫어요: 0
내용이 부정확하다면 싫어요를 클릭해주세요.